summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Binaries/DafnyPrelude.bpl15
-rw-r--r--Binaries/PrepareBoogieZip.bat41
-rw-r--r--Binaries/UnivBackPred2.smt23
-rw-r--r--Chalice/build.sbt2
-rw-r--r--Chalice/chalice.bat4
-rw-r--r--Chalice/scripts/create_release/create_release.bat2
-rw-r--r--Chalice/src/main/scala/Ast.scala6
-rw-r--r--Chalice/src/main/scala/Boogie.scala6
-rw-r--r--Chalice/src/main/scala/Chalice.scala109
-rw-r--r--Chalice/src/main/scala/Parser.scala7
-rw-r--r--Chalice/src/main/scala/Prelude.scala159
-rw-r--r--Chalice/src/main/scala/Resolver.scala61
-rw-r--r--Chalice/src/main/scala/SmokeTest.scala2
-rw-r--r--Chalice/src/main/scala/Translator.scala900
-rw-r--r--Chalice/tests/examples/AVLTree.iterative.output.txt2
-rw-r--r--Chalice/tests/examples/AVLTree.nokeys.output.txt2
-rw-r--r--Chalice/tests/examples/AssociationList.output.txt2
-rw-r--r--Chalice/tests/examples/BackgroundComputation.output.txt2
-rw-r--r--Chalice/tests/examples/CopyLessMessagePassing-with-ack.output.txt2
-rw-r--r--Chalice/tests/examples/CopyLessMessagePassing-with-ack2.output.txt2
-rw-r--r--Chalice/tests/examples/CopyLessMessagePassing.output.txt2
-rw-r--r--Chalice/tests/examples/FictionallyDisjointCells.output.txt2
-rw-r--r--Chalice/tests/examples/ForkJoin.output.txt2
-rw-r--r--Chalice/tests/examples/HandOverHand.output.txt2
-rw-r--r--Chalice/tests/examples/OwickiGries.output.txt2
-rw-r--r--Chalice/tests/examples/PetersonsAlgorithm.output.txt2
-rw-r--r--Chalice/tests/examples/ProdConsChannel.output.txt2
-rw-r--r--Chalice/tests/examples/RockBand.output.txt2
-rw-r--r--Chalice/tests/examples/Sieve.output.txt2
-rw-r--r--Chalice/tests/examples/Solver.output.txt2
-rw-r--r--Chalice/tests/examples/TreeOfWorker.output.txt2
-rw-r--r--Chalice/tests/examples/UnboundedThreads.output.txt2
-rw-r--r--Chalice/tests/examples/cell.output.txt2
-rw-r--r--Chalice/tests/examples/dining-philosophers.output.txt2
-rw-r--r--Chalice/tests/examples/iterator.output.txt2
-rw-r--r--Chalice/tests/examples/iterator2.output.txt2
-rw-r--r--Chalice/tests/examples/linkedlist.chalice34
-rw-r--r--Chalice/tests/examples/linkedlist.output.txt3
-rw-r--r--Chalice/tests/examples/list-reverse.output.txt2
-rw-r--r--Chalice/tests/examples/lseg.chalice86
-rw-r--r--Chalice/tests/examples/lseg.output.txt4
-rw-r--r--Chalice/tests/examples/producer-consumer.output.txt2
-rw-r--r--Chalice/tests/examples/swap.output.txt2
-rw-r--r--Chalice/tests/general-tests/FunctionPostcondition.chalice10
-rw-r--r--Chalice/tests/general-tests/FunctionPostcondition.output.txt4
-rw-r--r--Chalice/tests/general-tests/ImplicitLocals.output.txt2
-rw-r--r--Chalice/tests/general-tests/LoopLockChange.output.txt2
-rw-r--r--Chalice/tests/general-tests/RockBand-automagic.output.txt2
-rw-r--r--Chalice/tests/general-tests/SmokeTestTest.output.txt2
-rw-r--r--Chalice/tests/general-tests/cell-defaults.output.txt2
-rw-r--r--Chalice/tests/general-tests/counter.output.txt2
-rw-r--r--Chalice/tests/general-tests/ll-lastnode.chalice82
-rw-r--r--Chalice/tests/general-tests/ll-lastnode.output.txt6
-rw-r--r--Chalice/tests/general-tests/nestedPredicates.chalice114
-rw-r--r--Chalice/tests/general-tests/nestedPredicates.output.txt12
-rw-r--r--Chalice/tests/general-tests/prog1.output.txt2
-rw-r--r--Chalice/tests/general-tests/prog2.output.txt2
-rw-r--r--Chalice/tests/general-tests/prog3.output.txt2
-rw-r--r--Chalice/tests/general-tests/prog4.output.txt2
-rw-r--r--Chalice/tests/general-tests/quantifiers.output.txt2
-rw-r--r--Chalice/tests/general-tests/triggers.chalice81
-rw-r--r--Chalice/tests/general-tests/triggers.output.txt7
-rw-r--r--Chalice/tests/permission-model/basic.output.txt2
-rw-r--r--Chalice/tests/permission-model/channels.output.txt2
-rw-r--r--Chalice/tests/permission-model/locks.output.txt2
-rw-r--r--Chalice/tests/permission-model/peculiar.output.txt2
-rw-r--r--Chalice/tests/permission-model/permission_arithmetic.output.txt2
-rw-r--r--Chalice/tests/permission-model/predicates.output.txt2
-rw-r--r--Chalice/tests/permission-model/scaling.chalice71
-rw-r--r--Chalice/tests/permission-model/scaling.output.txt14
-rw-r--r--Chalice/tests/permission-model/sequences.output.txt2
-rw-r--r--Chalice/tests/predicates/FoldUnfoldExperiments.output.txt2
-rw-r--r--Chalice/tests/predicates/LinkedList-various.chalice176
-rw-r--r--Chalice/tests/predicates/LinkedList-various.output.txt4
-rw-r--r--Chalice/tests/predicates/aux-info.output.txt2
-rw-r--r--Chalice/tests/predicates/framing-fields.chalice3
-rw-r--r--Chalice/tests/predicates/framing-fields.output.txt4
-rw-r--r--Chalice/tests/predicates/framing-functions.output.txt2
-rw-r--r--Chalice/tests/predicates/list-reverse-extra-unfold-fold.chalice51
-rw-r--r--Chalice/tests/predicates/list-reverse-extra-unfold-fold.output.txt4
-rw-r--r--Chalice/tests/predicates/mutual-dependence.output.txt2
-rw-r--r--Chalice/tests/predicates/setset.output.txt2
-rw-r--r--Chalice/tests/predicates/test.chalice3
-rw-r--r--Chalice/tests/predicates/test.output.txt3
-rw-r--r--Chalice/tests/predicates/test1.output.txt2
-rw-r--r--Chalice/tests/predicates/test10.output.txt2
-rw-r--r--Chalice/tests/predicates/test2.output.txt2
-rw-r--r--Chalice/tests/predicates/test3.output.txt2
-rw-r--r--Chalice/tests/predicates/test4.output.txt2
-rw-r--r--Chalice/tests/predicates/test7.output.txt2
-rw-r--r--Chalice/tests/predicates/test8.output.txt2
-rw-r--r--Chalice/tests/predicates/unfolding.chalice1
-rw-r--r--Chalice/tests/predicates/unfolding.output.txt2
-rw-r--r--Chalice/tests/regressions/internal-bug-1.output.txt2
-rw-r--r--Chalice/tests/regressions/internal-bug-2.output.txt2
-rw-r--r--Chalice/tests/regressions/internal-bug-4.chalice17
-rw-r--r--Chalice/tests/regressions/internal-bug-4.output.txt6
-rw-r--r--Chalice/tests/regressions/internal-bug-5.chalice38
-rw-r--r--Chalice/tests/regressions/internal-bug-5.output.txt5
-rw-r--r--Chalice/tests/regressions/internal-bug-6.chalice10
-rw-r--r--Chalice/tests/regressions/internal-bug-6.output.txt4
-rw-r--r--Chalice/tests/regressions/internal-bug-7.chalice26
-rw-r--r--Chalice/tests/regressions/internal-bug-7.output.txt4
-rw-r--r--Chalice/tests/regressions/workitem-10189.chalice23
-rw-r--r--Chalice/tests/regressions/workitem-10189.output.txt4
-rw-r--r--Chalice/tests/regressions/workitem-10192.output.txt2
-rw-r--r--Chalice/tests/regressions/workitem-10194.output.txt2
-rw-r--r--Chalice/tests/regressions/workitem-10195.output.txt2
-rw-r--r--Chalice/tests/regressions/workitem-10196.output.txt2
-rw-r--r--Chalice/tests/regressions/workitem-10197.output.txt2
-rw-r--r--Chalice/tests/regressions/workitem-10198.output.txt2
-rw-r--r--Chalice/tests/regressions/workitem-10199.output.txt2
-rw-r--r--Chalice/tests/regressions/workitem-10200.output.txt2
-rw-r--r--Chalice/tests/regressions/workitem-10208.chalice41
-rw-r--r--Chalice/tests/regressions/workitem-10208.output.txt8
-rw-r--r--Chalice/tests/regressions/workitem-10221.chalice158
-rw-r--r--Chalice/tests/regressions/workitem-10221.output.txt4
-rw-r--r--Chalice/tests/regressions/workitem-10223.output.txt2
-rw-r--r--Chalice/tests/regressions/workitem-8234.output.txt2
-rw-r--r--Chalice/tests/regressions/workitem-8236.output.txt2
-rw-r--r--Chalice/tests/regressions/workitem-9978.output.txt2
-rw-r--r--Chalice/tests/test-scripts/getboogieoutput.bat2
-rw-r--r--Chalice/tests/test-scripts/reg_test.bat8
-rw-r--r--Chalice/tests/test-scripts/test.bat2
-rw-r--r--Source/AbsInt/AbsInt.csproj7
-rw-r--r--Source/AbsInt/AbstractInterpretation.cs916
-rw-r--r--Source/AbsInt/ExprFactories.cs275
-rw-r--r--Source/AbsInt/IntervalDomain.cs33
-rw-r--r--Source/AbsInt/LoopInvariantsOnDemand.cs84
-rw-r--r--Source/AbsInt/NativeLattice.cs20
-rw-r--r--Source/Basetypes/Basetypes.csproj1
-rw-r--r--Source/Basetypes/BigDec.cs313
-rw-r--r--Source/Boogie.sln137
-rw-r--r--Source/BoogieDriver/BoogieDriver.cs22
-rw-r--r--Source/BoogieDriver/BoogieDriver.csproj14
-rw-r--r--Source/Core/Absy.cs204
-rw-r--r--Source/Core/AbsyCmd.cs14
-rw-r--r--Source/Core/AbsyExpr.cs865
-rw-r--r--Source/Core/AbsyQuant.cs242
-rw-r--r--Source/Core/AbsyType.cs26
-rw-r--r--Source/Core/BoogiePL.atg58
-rw-r--r--Source/Core/CommandLineOptions.cs64
-rw-r--r--Source/Core/Core.csproj5
-rw-r--r--Source/Core/DeadVarElim.cs4
-rw-r--r--Source/Core/GraphAlgorithms.cs244
-rw-r--r--Source/Core/LoopUnroll.cs1
-rw-r--r--Source/Core/Makefile7
-rw-r--r--Source/Core/Parser.cs982
-rw-r--r--Source/Core/Scanner.cs355
-rw-r--r--Source/Core/StandardVisitor.cs5
-rw-r--r--Source/Core/Util.cs10
-rw-r--r--Source/Dafny/Cloner.cs4
-rw-r--r--Source/Dafny/Dafny.atg79
-rw-r--r--Source/Dafny/DafnyAst.cs107
-rw-r--r--Source/Dafny/DafnyPipeline.csproj4
-rw-r--r--Source/Dafny/Printer.cs35
-rw-r--r--Source/Dafny/Resolver.cs52
-rw-r--r--Source/Dafny/Translator.cs55
-rw-r--r--Source/DafnyDriver/DafnyDriver.cs12
-rw-r--r--Source/DafnyDriver/DafnyDriver.csproj3
-rw-r--r--Source/Doomed/DoomCheck.cs (renamed from Source/VCGeneration/DoomCheck.cs)3
-rw-r--r--Source/Doomed/DoomErrorHandler.cs (renamed from Source/VCGeneration/DoomErrorHandler.cs)3
-rw-r--r--Source/Doomed/Doomed.csproj101
-rw-r--r--Source/Doomed/DoomedLoopUnrolling.cs (renamed from Source/VCGeneration/DoomedLoopUnrolling.cs)3
-rw-r--r--Source/Doomed/DoomedStrategy.cs (renamed from Source/VCGeneration/DoomedStrategy.cs)3
-rw-r--r--Source/Doomed/HasseDiagram.cs (renamed from Source/VCGeneration/HasseDiagram.cs)3
-rw-r--r--Source/Doomed/VCDoomed.cs (renamed from Source/VCGeneration/VCDoomed.cs)3
-rw-r--r--Source/GPUVerify.sln22
-rw-r--r--Source/GPUVerify/ArrayControlFlowAnalyser.cs12
-rw-r--r--Source/GPUVerify/BarrierInvariantDescriptor.cs43
-rw-r--r--Source/GPUVerify/BinaryBarrierInvariantDescriptor.cs64
-rw-r--r--Source/GPUVerify/GPUVerifier.cs4465
-rw-r--r--Source/GPUVerify/GPUVerify.csproj17
-rw-r--r--Source/GPUVerify/IRaceInstrumenter.cs58
-rw-r--r--Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs109
-rw-r--r--Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs122
-rw-r--r--Source/GPUVerify/KernelDualiser.cs224
-rw-r--r--Source/GPUVerify/LoopInvariantGenerator.cs516
-rw-r--r--Source/GPUVerify/NonLocalAccessCollector.cs1
-rw-r--r--Source/GPUVerify/NullRaceInstrumenter.cs119
-rw-r--r--Source/GPUVerify/RaceInstrumenter.cs2181
-rw-r--r--Source/GPUVerify/UnaryBarrierInvariantDescriptor.cs51
-rw-r--r--Source/GPUVerify/UniformExpressionAnalysisVisitor.cs39
-rw-r--r--Source/GPUVerify/UniformityAnalyser.cs425
-rw-r--r--Source/GPUVerify/VariableDualiser.cs67
-rw-r--r--Source/GPUVerifyBoogieDriver/GPUVerifyBoogieDriver.cs1634
-rw-r--r--Source/GPUVerifyBoogieDriver/GPUVerifyBoogieDriver.csproj3
-rw-r--r--Source/GPUVerifyBoogieDriver/GetIfOfIfThenElseVisitor.cs61
-rw-r--r--Source/GPUVerifyBoogieDriver/GetRHSOfEqualityVisitor.cs43
-rw-r--r--Source/GPUVerifyBoogieDriver/GetThenOfIfThenElseVisitor.cs39
-rw-r--r--Source/Graph/Graph.cs2220
-rw-r--r--Source/Houdini/Houdini.cs20
-rw-r--r--Source/Houdini/Houdini.csproj4
-rw-r--r--Source/Predication/BlockPredicator.cs (renamed from Source/VCGeneration/BlockPredicator.cs)2
-rw-r--r--Source/Predication/Predication.csproj86
-rw-r--r--Source/Predication/SmartBlockPredicator.cs (renamed from Source/VCGeneration/SmartBlockPredicator.cs)283
-rw-r--r--Source/Predication/UniformityAnalyser.cs591
-rw-r--r--Source/Provers/Isabelle/Isabelle.csproj210
-rw-r--r--Source/Provers/Isabelle/Prover.cs1083
-rw-r--r--Source/Provers/Isabelle/cce.cs193
-rw-r--r--Source/Provers/SMTLib/SMTLib.csproj4
-rw-r--r--Source/Provers/SMTLib/SMTLibLineariser.cs39
-rw-r--r--Source/Provers/SMTLib/SMTLibNamer.cs6
-rw-r--r--Source/Provers/SMTLib/TypeDeclCollector.cs2
-rw-r--r--Source/Provers/Simplify/Let2ImpliesVisitor.cs236
-rw-r--r--Source/Provers/Simplify/Prover.cs656
-rw-r--r--Source/Provers/Simplify/ProverInterface.cs868
-rw-r--r--Source/Provers/Simplify/Simplify.csproj210
-rw-r--r--Source/Provers/Simplify/cce.cs193
-rw-r--r--Source/Provers/Z3/Inspector.cs162
-rw-r--r--Source/Provers/Z3/Prover.cs937
-rw-r--r--Source/Provers/Z3/ProverInterface.cs427
-rw-r--r--Source/Provers/Z3/TypeDeclCollector.cs398
-rw-r--r--Source/Provers/Z3/Z3.csproj218
-rw-r--r--Source/Provers/Z3/cce.cs193
-rw-r--r--Source/Provers/Z3api/ContextLayer.cs38
-rw-r--r--Source/Provers/Z3api/TypeAdapter.cs9
-rw-r--r--Source/Provers/Z3api/VCExprVisitor.cs60
-rw-r--r--Source/Provers/Z3api/Z3api.csproj4
-rw-r--r--Source/VCExpr/BigLiteralAbstracter.cs8
-rw-r--r--Source/VCExpr/Boogie2VCExpr.cs77
-rw-r--r--Source/VCExpr/SimplifyLikeLineariser.cs63
-rw-r--r--Source/VCExpr/TypeErasure.cs48
-rw-r--r--Source/VCExpr/VCExpr.csproj4
-rw-r--r--Source/VCExpr/VCExprAST.cs74
-rw-r--r--Source/VCExpr/VCExprASTPrinter.cs24
-rw-r--r--Source/VCExpr/VCExprASTVisitors.cs40
-rw-r--r--Source/VCGeneration/ConditionGeneration.cs3
-rw-r--r--Source/VCGeneration/GraphAlgorithms.cs99
-rw-r--r--Source/VCGeneration/StratifiedVC.cs3
-rw-r--r--Source/VCGeneration/VC.cs34
-rw-r--r--Source/VCGeneration/VCGeneration.csproj27
-rw-r--r--Test/VSComp2010/Problem2-Invert.dfy1
-rw-r--r--Test/aitest0/Answer28
-rw-r--r--Test/aitest0/runtest.bat2
-rw-r--r--Test/aitest1/Answer69
-rw-r--r--Test/aitest1/runtest.bat4
-rw-r--r--Test/aitest9/runtest.bat2
-rw-r--r--Test/dafny0/Answer54
-rw-r--r--Test/dafny0/Calculations.dfy37
-rw-r--r--Test/dafny0/CoPredicates.dfy11
-rw-r--r--Test/dafny0/ParseErrors.dfy58
-rw-r--r--Test/dafny0/ResolutionErrors.dfy29
-rw-r--r--Test/dafny0/runtest.bat2
-rw-r--r--Test/dafny2/Answer4
-rw-r--r--Test/dafny2/Calculations.dfy209
-rw-r--r--Test/dafny2/runtest.bat2
-rw-r--r--Test/inline/Answer6
-rw-r--r--Test/livevars/bla1.bpl2
-rw-r--r--Test/livevars/daytona_bug2_ioctl_example_1.bpl2
-rw-r--r--Test/livevars/daytona_bug2_ioctl_example_2.bpl2
-rw-r--r--Test/livevars/stack_overflow.bpl2
-rw-r--r--Test/prover/Answer16
-rw-r--r--Test/prover/EQ_v2.Eval__v4.Eval_out.bpl4
-rw-r--r--Test/test0/Answer40
-rw-r--r--Test/test0/BadLabels1.bpl2
-rw-r--r--Test/test0/ModifiedBag.bpl2
-rw-r--r--Test/test0/PrettyPrint.bpl25
-rw-r--r--Test/test0/Prog0.bpl2
-rw-r--r--Test/test1/Answer19
-rw-r--r--Test/test1/IntReal.bpl48
-rw-r--r--Test/test1/runtest.bat1
-rw-r--r--Test/test15/Answer120
-rw-r--r--Test/test2/strings-no-where.bpl22
-rw-r--r--Test/test2/strings-where.bpl22
-rw-r--r--Test/test20/Answer8
-rw-r--r--Test/test20/Prog0.bpl2
-rw-r--r--Test/test20/Prog1.bpl2
-rw-r--r--Test/test21/Answer9
-rw-r--r--Test/test21/Real.bpl17
-rw-r--r--Test/test21/runtest.bat4
-rw-r--r--Util/Emacs/boogie-mode.el4
-rw-r--r--Util/Emacs/dafny-mode.el2
-rw-r--r--Util/VS2010/Boogie/BoogieLanguageService/Grammar.cs15
-rw-r--r--Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs3
-rw-r--r--Util/VS2010/DafnyExtension/DafnyExtension.sln4
-rw-r--r--Util/VS2010/DafnyExtension/DafnyExtension/DafnyDriver.cs9
-rw-r--r--Util/VS2010/DafnyExtension/DafnyExtension/DafnyExtension.csproj14
-rw-r--r--Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs5
-rw-r--r--Util/VS2010/DafnyExtension/DafnyExtension/source.extension.vsixmanifest3
-rw-r--r--Util/latex/boogie.sty4
-rw-r--r--Util/latex/dafny.sty2
-rw-r--r--Util/vim/syntax/boogie.vim4
-rw-r--r--Util/vim/syntax/dafny.vim2
-rw-r--r--_admin/Boogie/aste/summary.log380
285 files changed, 13161 insertions, 16324 deletions
diff --git a/Binaries/DafnyPrelude.bpl b/Binaries/DafnyPrelude.bpl
index e6d05bea..fafc9484 100644
--- a/Binaries/DafnyPrelude.bpl
+++ b/Binaries/DafnyPrelude.bpl
@@ -647,18 +647,3 @@ type TickType;
var $Tick: TickType;
// ---------------------------------------------------------------
-// -- Arithmetic -------------------------------------------------
-// ---------------------------------------------------------------
-
-// the connection between % and /
-axiom (forall x:int, y:int :: {x % y} {x / y} x % y == x - x / y * y);
-
-// remainder is always Euclidean Modulus.
-axiom (forall x:int, y:int :: {x % y} 0 < y ==> 0 <= x % y && x % y < y);
-axiom (forall x:int, y:int :: {x % y} y < 0 ==> 0 <= x % y && x % y < -y);
-
-// the following axiom has some unfortunate matching, but it does state a property about % that
-// is sometimes useful
-axiom (forall a: int, b: int, d: int :: { a % d, b % d } 2 <= d && a % d == b % d && a < b ==> a + d <= b);
-
-// ---------------------------------------------------------------
diff --git a/Binaries/PrepareBoogieZip.bat b/Binaries/PrepareBoogieZip.bat
index 9edeec4a..1f64a31c 100644
--- a/Binaries/PrepareBoogieZip.bat
+++ b/Binaries/PrepareBoogieZip.bat
@@ -7,33 +7,28 @@ if exist %DEST_DIR% del /q %DEST_DIR%\*
if not exist %DEST_DIR% mkdir %DEST_DIR%
for %%f in (
- AbsInt.dll AbsInt.pdb
- AIFramework.dll AIFramework.pdb
- Basetypes.dll Basetypes.pdb
- Boogie.exe Boogie.pdb
- BVD.exe BVD.pdb
- CodeContractsExtender.dll CodeContractsExtender.pdb
- Core.dll Core.pdb
- Dafny.exe Dafny.pdb
- DafnyPipeline.dll DafnyPipeline.pdb
- Graph.dll Graph.pdb
- Houdini.dll Houdini.pdb
- Model.dll Model.pdb
- ParserHelper.dll ParserHelper.pdb
- Provers.Isabelle.dll Provers.Isabelle.pdb
- Provers.Simplify.dll Provers.Simplify.pdb
- Provers.SMTLib.dll Provers.SMTLib.pdb
- Provers.TPTP.dll Provers.TPTP.pdb
- Provers.Z3.dll Provers.Z3.pdb
- VCExpr.dll VCExpr.pdb
- VCGeneration.dll VCGeneration.pdb
- DafnyPrelude.bpl
- DafnyRuntime.cs
+ AbsInt.dll AbsInt.pdb
+ Basetypes.dll Basetypes.pdb
+ Boogie.exe Boogie.pdb
+ CodeContractsExtender.dll CodeContractsExtender.pdb
+ Core.dll Core.pdb
+ Dafny.exe Dafny.pdb
+ DafnyPrelude.bpl DafnyRuntime.cs
+ DafnyPipeline.dll DafnyPipeline.pdb
+ Graph.dll Graph.pdb
+ Houdini.dll
+ Model.dll Model.pdb
+ ParserHelper.dll ParserHelper.pdb
+ Provers.SMTLib.dll Provers.SMTLib.pdb
TypedUnivBackPred2.sx
- UnivBackPred2.smt2
+ UnivBackPred2.smt UnivBackPred2.smt2
UnivBackPred2.sx
+ VCExpr.dll VCExpr.pdb
+ VCGeneration.dll VCGeneration.pdb
) do (
copy %%f %DEST_DIR%
)
+xcopy /E /I /Y CodeContracts "%DEST_DIR%/CodeContracts"
+
echo Done. Now, manually put the contents of the %DEST_DIR% directory into Boogie.zip
diff --git a/Binaries/UnivBackPred2.smt2 b/Binaries/UnivBackPred2.smt2
index d3e3777f..9bb05bfb 100644
--- a/Binaries/UnivBackPred2.smt2
+++ b/Binaries/UnivBackPred2.smt2
@@ -3,7 +3,6 @@
(set-info :category "industrial")
(declare-sort |T@U| 0)
(declare-sort |T@T| 0)
-(declare-fun int_div (Int Int) Int)
-(declare-fun int_mod (Int Int) Int)
+(declare-fun real_pow (Real Real) Real)
(declare-fun UOrdering2 (|T@U| |T@U|) Bool)
(declare-fun UOrdering3 (|T@T| |T@U| |T@U|) Bool)
diff --git a/Chalice/build.sbt b/Chalice/build.sbt
index 3fa72ec5..ea32574f 100644
--- a/Chalice/build.sbt
+++ b/Chalice/build.sbt
@@ -3,7 +3,7 @@ name := "Chalice"
version := "1.0"
-scalaVersion := "2.8.1"
+scalaVersion := "2.9.2"
scalacOptions += "-deprecation"
diff --git a/Chalice/chalice.bat b/Chalice/chalice.bat
index 6400ca7b..66dc095c 100644
--- a/Chalice/chalice.bat
+++ b/Chalice/chalice.bat
@@ -12,11 +12,11 @@ if not %ERRORLEVEL%==0 (
)
-set SCALA_DIR=scala-2.8.1
+set SCALA_DIR=scala-2.9.2
REM Set classpath elements
set __CP.SCALA_LIB="%ROOT_DIR%project\boot\%SCALA_DIR%\lib\scala-library.jar"
-set __CP.CHALICE="%ROOT_DIR%target\%SCALA_DIR%.final\classes"
+set __CP.CHALICE="%ROOT_DIR%target\%SCALA_DIR%\classes"
REM Assemble classpath and check if all classpath elements exist
set CP=
diff --git a/Chalice/scripts/create_release/create_release.bat b/Chalice/scripts/create_release/create_release.bat
index a0d67fd9..5aadd36e 100644
--- a/Chalice/scripts/create_release/create_release.bat
+++ b/Chalice/scripts/create_release/create_release.bat
@@ -6,7 +6,7 @@ set BASE_DIR=%~dp0\..\..
set RELEASE_DIR_SRC=%~dp0\files
set RELEASE_DIR_DST=%~dp0\release
-set CHALICE_JAR_SRC=%BASE_DIR%\target\scala-2.8.1.final\chalice_2.8.1-1.0.jar
+set CHALICE_JAR_SRC=%BASE_DIR%\target\scala-2.9.2\chalice_2.9.2-1.0.jar
set CHALICE_JAR_DST=%RELEASE_DIR_DST%\chalice.jar
pushd %BASE_DIR%
diff --git a/Chalice/src/main/scala/Ast.scala b/Chalice/src/main/scala/Ast.scala
index 1cfd173e..b8a92f7c 100644
--- a/Chalice/src/main/scala/Ast.scala
+++ b/Chalice/src/main/scala/Ast.scala
@@ -182,6 +182,7 @@ case class Method(id: String, ins: List[Variable], outs: List[Variable], spec: L
override def Outs = outs
}
case class Predicate(id: String, private val rawDefinition: Expression) extends NamedMember(id) {
+ TranslatorPrelude.addPredicate(this)
lazy val definition: Expression = rawDefinition.transform {
case Epsilon | MethodEpsilon => Some(PredicateEpsilon(None))
case _ => None
@@ -209,8 +210,13 @@ case class Function(id: String, ins: List[Variable], out: Type, spec: List[Speci
result
}
var isUnlimited = false
+ var isStatic = false
var isRecursive = false
var SCC: List[Function] = Nil
+ // the 'height' of this function is determined by a topological sort of the
+ // condensation of the call graph; mutually recursive functions get the same
+ // height.
+ var height: Int = -1
}
case class Condition(id: String, where: Option[Expression]) extends NamedMember(id)
case class Variable(id: String, t: Type, isGhost: Boolean, isImmutable: Boolean) extends ASTNode {
diff --git a/Chalice/src/main/scala/Boogie.scala b/Chalice/src/main/scala/Boogie.scala
index 900ad6d1..e775b688 100644
--- a/Chalice/src/main/scala/Boogie.scala
+++ b/Chalice/src/main/scala/Boogie.scala
@@ -66,8 +66,8 @@ object Boogie {
def +(that: Expr) = BinaryExpr("+", this, that)
def -(that: Expr) = BinaryExpr("-", this, that)
def *(that: Expr) = BinaryExpr("*", this, that)
- def /(that: Expr) = BinaryExpr("/", this, that)
- def %(that: Expr) = BinaryExpr("%", this, that)
+ def /(that: Expr) = BinaryExpr("div", this, that)
+ def %(that: Expr) = BinaryExpr("mod", this, that)
def := (that: Expr) = Assign(this, that)
def apply(e: Expr, f: Expr) = new MapSelect(this, e, Some(f))
def apply(e: Expr) = new MapSelect(this, e, None)
@@ -78,6 +78,7 @@ object Boogie {
def store(e: Expr, f: Expr, rhs: Expr) = MapUpdate(this, e, Some(f), rhs)
}
case class IntLiteral(n: Int) extends Expr
+ case class RealLiteral(d: Double) extends Expr
case class BoolLiteral(b: Boolean) extends Expr
case class Null() extends Expr
case class VarExpr(id: String) extends Expr {
@@ -252,6 +253,7 @@ object Boogie {
}
def PrintExpr(e: Expr, useParens: Boolean): String = e match {
case IntLiteral(n) => n.toString
+ case RealLiteral(d) => d.toString
case BoolLiteral(b) => b.toString
case Null() => "null"
case VarExpr(id) => id
diff --git a/Chalice/src/main/scala/Chalice.scala b/Chalice/src/main/scala/Chalice.scala
index 077e5c46..60f5f443 100644
--- a/Chalice/src/main/scala/Chalice.scala
+++ b/Chalice/src/main/scala/Chalice.scala
@@ -34,13 +34,10 @@ object Chalice {
private[chalice] var skipDeadlockChecks = false: Boolean;
private[chalice] var skipTermination = false: Boolean;
private[chalice] var noFreeAssume = false: Boolean;
- // percentageSupport 0: use multiplication directly
- // percentageSupport 1: fix Permission$denominator as constant (possibly unsound for small values of the constant?)
- // percentageSupport 2: use function and provide some (redundant) axioms
- // percentageSupport 3: use an uninterpreted function and axiomatize the properties of multiplication
- private[chalice] var percentageSupport = 2;
+ private[chalice] var percentageSupport = 0;
private[chalice] var smoke = false;
private[chalice] var smokeAll = false;
+ private[chalice] var timingVerbosity = 1;
/**
* Holds all command line arguments not stored in fields of Chalice.
@@ -126,22 +123,28 @@ object Chalice {
"smoke testing; try to find unreachable code, preconditions/invariants/predicates that are equivalent to false and assumptions that introduce contradictions, by trying to prove 'false' at various positions."),
"smokeAll" -> (
{() => smokeAll = true; smoke = true},
- "aggressive smoke testing; try to prove false after every statement.")
+ "aggressive smoke testing; try to prove false after every statement."),
+ "time" -> (
+ {() => timingVerbosity = 2},
+ "sets /time:2")
)
// help text for options with arguments
val nonBooleanOptions = ListMap(
"boogie:<file>" -> "use the executable of Boogie at <file>",
"print:<file>" -> "print the Boogie program used for verification into file <file>",
+ "time:<n>" -> ("output timing information\n"+
+ "0: no information is included\n"+
+ "1: the overall verification time is output (default)\n"+
+ "2: detailed timings for each phase of the verification are output\n"+
+ "3: (used for testing only) output the overall verification time on stderr"),
"defaults:<level>" -> ("defaults to reduce specification overhead\n"+
"level 0 or below: no defaults\n"+
"level 1: unfold predicates with receiver this in pre and postconditions\n"+
"level 2: unfold predicates and functions with receiver this in pre and postconditions\n"+
"level 3 or above: level 2 + autoMagic"),
"percentageSupport:<n>" -> ("determin how percentage permissions are translated to Boogie\n"+
- "0: use multiplication directly (can cause performance problems)\n"+
- "1: fix Permission$denominator as constant (possibly unsound)\n"+
- "2: use a function and provide some (redundant) axioms\n"+
- "3: use an uninterpreted function and axiomatize the properties of multiplication"),
+ "0: use multiplication directly (default)\n"+
+ "1: use a function and provide some (redundant) axioms")+
"boogieOpt:<arg>, /bo:<arg>" -> "specify additional Boogie options"
)
lazy val help = {
@@ -169,10 +172,17 @@ object Chalice {
else if (a.startsWith("/percentageSupport:") || a.startsWith("-percentageSupport:")) {
try {
val in = Integer.parseInt(a.substring(19));
- if (in < 0 || in > 3) CommandLineError("/percentageSupport takes only values 0,1,2 or 3", help)
+ if (in < 0 || in > 1) CommandLineError("/percentageSupport takes only values 0 or 1", help)
else percentageSupport = in
} catch { case _ => CommandLineError("/percentageSupport takes integer argument", help); }
}
+ else if (a.startsWith("/time:") || a.startsWith("-time:")) {
+ try {
+ val in = Integer.parseInt(a.substring(6));
+ if (in < 0 || in > 3) CommandLineError("/time takes only values 0, 1, 2 or 3", help)
+ else timingVerbosity = in
+ } catch { case _ => CommandLineError("/time takes integer argument", help); }
+ }
else if (a.startsWith("-boogieOpt:") || a.startsWith("/boogieOpt:"))
aBoogieArgs += ("\"/" + a.substring(11) + "\"" + " ")
else if (a.startsWith("-bo:") || a.startsWith("/bo:"))
@@ -198,9 +208,7 @@ object Chalice {
percentageSupport match {
case 0 => TranslatorPrelude.addComponent(PercentageStandardPL)
- case 1 => TranslatorPrelude.addComponent(PercentageStandardPL, PercentageFixedDenominatorPL)
- case 2 => TranslatorPrelude.addComponent(PercentageFunctionPL)
- case 3 => TranslatorPrelude.addComponent(PercentageUninterpretedFunctionPL)
+ case 1 => TranslatorPrelude.addComponent(PercentageFunctionPL)
}
// check that input files exist
@@ -251,7 +259,7 @@ object Chalice {
if (vsMode)
ReportError(e.next.pos, e.msg);
else
- Console.err.println("Error: " + e);
+ Console.out.println("Error: " + e);
Nil
case parser.Success(prog, _) =>
val pprog = if (smoke) SmokeTest.smokeProgram(prog) else prog
@@ -268,36 +276,64 @@ object Chalice {
// typecheck program
Resolver.Resolve(program) match {
case Resolver.Errors(msgs) =>
- if (!vsMode) Console.err.println("The program did not typecheck.");
+ if (!vsMode) Console.out.println("The program did not typecheck.");
msgs foreach { msg => ReportError(msg._1, msg._2) };
false;
case Resolver.Success() =>
true
}
}
-
+
+ object VerificationSteps extends Enumeration {
+ type VerificationSteps = Value
+ val Init = Value("Init")
+ val Parse = Value("Parse")
+ val TypeCheck = Value("TypeCheck")
+ val PrintProgram = Value("PrintProgram")
+ val Translate = Value("Translate")
+ val Boogie = Value("Boogie")
+ val GenerateCode = Value("GenerateCode")
+ }
+
def main(args: Array[String]): Unit = {
+ var timings = scala.collection.immutable.ListMap[VerificationSteps.Value, Long]()
+ for (step <- VerificationSteps.values) timings += (step -> 0)
+ var startTime = System.nanoTime
+ var tmpTime = startTime
+
//Parse command line arguments
val params = parseCommandLine(args) match {
case Some(p) => p
case None => return //invalid arguments, help has been displayed
}
-
+
+ timings += (VerificationSteps.Init -> (System.nanoTime - tmpTime))
+ tmpTime = System.nanoTime
+
try {
val program = parsePrograms(params) match {
case Some(p) => p
case None => return //illegal program, errors have already been displayed
}
+
+ timings += (VerificationSteps.Parse -> (System.nanoTime - tmpTime))
+ tmpTime = System.nanoTime
if(!params.doTypecheck || !typecheckProgram(params, program))
return ;
-
+
+ timings += (VerificationSteps.TypeCheck -> (System.nanoTime - tmpTime))
+ tmpTime = System.nanoTime
+
if (params.printProgram) {
Console.out.println("Program after type checking: ");
PrintProgram.P(program)
}
+
+ timings += (VerificationSteps.PrintProgram -> (System.nanoTime - tmpTime))
+ tmpTime = System.nanoTime
if(!params.doTranslate)
return;
@@ -317,6 +353,9 @@ object Chalice {
val translator = new Translator();
var bplProg: List[Boogie.Decl] = Nil
bplProg = translator.translateProgram(program);
+
+ timings += (VerificationSteps.Translate -> (System.nanoTime - tmpTime))
+ tmpTime = System.nanoTime
// write to out.bpl
val bplText = TranslatorPrelude.P + (bplProg map Boogie.Print).foldLeft(""){ (a, b) => a + b };
@@ -347,7 +386,8 @@ object Chalice {
val boogieOutput: ListBuffer[String] = new ListBuffer()
while (line!=null){
if (!smoke) {
- Console.out.println(line);
+ if (previous_line != null) Console.out.println
+ Console.out.print(line);
Console.out.flush;
}
boogieOutput += line
@@ -356,11 +396,14 @@ object Chalice {
}
boogie.waitFor;
input.close;
+
+ timings += (VerificationSteps.Boogie -> (System.nanoTime - tmpTime))
+ tmpTime = System.nanoTime
// smoke test output
if (smoke) {
val output = SmokeTest.processBoogieOutput(boogieOutput.toList)
- Console.out.println(output);
+ Console.out.print(output);
Console.out.flush;
}
@@ -368,6 +411,9 @@ object Chalice {
if(params.gen && (previous_line != null) && previous_line.endsWith(" 0 errors")) { // hack
generateCSharpCode(params, program)
}
+
+ timings += (VerificationSteps.GenerateCode -> (System.nanoTime - tmpTime))
+ tmpTime = System.nanoTime
} catch {
case e:InternalErrorException => {
if (params.showFullStackTrace) {
@@ -388,6 +434,23 @@ object Chalice {
return
}
}
+
+ val time = System.nanoTime - startTime
+ if (timingVerbosity == 1) {
+ Console.out.println(" in " + ("%1.3f" format (time / 1000000000.0)) + " seconds")
+ } else if (timingVerbosity == 2) {
+ Console.out.println; Console.out.println
+ Console.out.println("Timings Information")
+ val max = (timings.keySet.toList.map(a => a.toString.length).sortWith( (a, b) => a > b )).head
+ for ((step, time) <- timings) {
+ Console.out.println(" " + step + ": " + (" "*(max - step.toString.length)) + ("%1.3f" format (time / 1000000000.0)) + " seconds")
+ }
+ } else {
+ Console.out.println
+ }
+ if (timingVerbosity == 3) {
+ Console.err.println(("%1.3f" format (time / 1000000000.0)))
+ }
}
def generateCSharpCode(params: CommandLineParameters, program: List[TopLevelDecl]): Unit = {
@@ -404,7 +467,7 @@ object Chalice {
}
def CommandLineError(msg: String, help: String) = {
- Console.err.println("Error: " + msg)
+ Console.out.println("Error: " + msg)
}
def ReportError(pos: Position, msg: String) = {
@@ -412,7 +475,7 @@ object Chalice {
val (r,c) = (pos.line, pos.column)
Console.out.println(r + "," + c + "," + r + "," + (c+5) + ":" + msg);
} else {
- Console.err.println(pos + ": " + msg)
+ Console.out.println(pos + ": " + msg)
}
}
diff --git a/Chalice/src/main/scala/Parser.scala b/Chalice/src/main/scala/Parser.scala
index d75cf9c8..9a4cd272 100644
--- a/Chalice/src/main/scala/Parser.scala
+++ b/Chalice/src/main/scala/Parser.scala
@@ -32,7 +32,7 @@ class Parser extends StandardTokenParsers {
"between", "and", "above", "below", "share", "unshare", "acquire", "release", "downgrade",
"lock", "fork", "join", "rd", "acc", "credit", "holds", "old", "assigned",
"call", "if", "else", "while", "invariant", "lockchange",
- "returns", "requires", "ensures", "where",
+ "returns", "requires", "ensures", "where", "static",
"int", "bool", "false", "true", "null", "string", "waitlevel", "lockbottom",
"module", "external",
"predicate", "function", "free", "send", "receive",
@@ -105,10 +105,11 @@ class Parser extends StandardTokenParsers {
}
def functionDecl = {
currentLocalVariables = Set[String]();
- ("unlimited" ?) ~ ("function" ~> ident) ~ formalParameters(true) ~ (":" ~> typeDecl) ~ (methodSpec*) ~ opt("{" ~> expression <~ "}") ^^ {
- case u ~ id ~ ins ~ out ~ specs ~ body => {
+ ("unlimited" ?) ~ ("static" ?) ~ ("function" ~> ident) ~ formalParameters(true) ~ (":" ~> typeDecl) ~ (methodSpec*) ~ opt("{" ~> expression <~ "}") ^^ {
+ case u ~ s ~ id ~ ins ~ out ~ specs ~ body => {
val f = Function(id, ins, out, specs, body);
if (u.isDefined) f.isUnlimited = true;
+ if (s.isDefined) f.isStatic = true;
f
}
}
diff --git a/Chalice/src/main/scala/Prelude.scala b/Chalice/src/main/scala/Prelude.scala
index f54cee2c..4a333f8e 100644
--- a/Chalice/src/main/scala/Prelude.scala
+++ b/Chalice/src/main/scala/Prelude.scala
@@ -18,15 +18,22 @@ object TranslatorPrelude {
def addComponent(c: PreludeComponent*): Unit = {
components ++= c
}
-
+
// removes a component from the prelude. use with great care, as other parts of
// the system could depend on the component c being present in the prelude.
def removeComponent(c: PreludeComponent*): Unit = {
components --= c
}
+
+ // records that a predicate occurs in the program (used for generating the
+ // correct triggers for an axiom in the prelude)
+ def addPredicate(p: Predicate*): Unit = {
+ predicates ++= p
+ }
+ val predicates: Set[Predicate] = Set()
// default components
- private val components: Set[PreludeComponent] = Set(CopyrightPL, TypesPL, PermissionTypesAndConstantsPL, CreditsAndMuPL, PermissionFunctionsAndAxiomsPL, IfThenElsePL, ArithmeticPL, StringPL)
+ private val components: Set[PreludeComponent] = Set(CopyrightPL, TypesPL, PermissionTypesAndConstantsPL, CreditsAndMuPL, PermissionFunctionsAndAxiomsPL, IfThenElsePL, StringPL)
// get the prelude (with all components currently included)
def P: String = {
@@ -46,7 +53,7 @@ object TranslatorPrelude {
sealed abstract class PreludeComponent {
// determines the order in which the components are output
def compare(that: PreludeComponent): Boolean = {
- val order: List[PreludeComponent] = List(CopyrightPL, TypesPL, PermissionTypesAndConstantsPL, PercentageFixedDenominatorPL, PercentageFunctionPL, PercentageUninterpretedFunctionPL, CreditsAndMuPL, PermissionFunctionsAndAxiomsPL, IfThenElsePL, ArithmeticPL, StringPL, AxiomatizationOfSequencesPL)
+ val order: List[PreludeComponent] = List(CopyrightPL, TypesPL, PermissionTypesAndConstantsPL, PercentageFunctionPL, CreditsAndMuPL, PermissionFunctionsAndAxiomsPL, IfThenElsePL, StringPL, AxiomatizationOfSequencesPL)
if (!order.contains(this)) false
else order.indexOf(this) < order.indexOf(that)
}
@@ -60,7 +67,8 @@ object TypesPL extends PreludeComponent {
val text = """
type Field a;
type HeapType = <a>[ref,Field a]a;
-type MaskType = <a>[ref,Field a][PermissionComponent]int;
+type MaskType = <a>[ref,Field a][PermissionComponent]real;
+type PMaskType = <a>[ref,Field a]bool;
type CreditsType = [ref]int;
type ref;
const null: ref;
@@ -74,67 +82,52 @@ const unique perm$R: PermissionComponent;
const unique perm$N: PermissionComponent;
var Mask: MaskType where IsGoodMask(Mask);
var SecMask: MaskType where IsGoodMask(SecMask);
-const Permission$denominator: int;
-axiom Permission$denominator > 0;
-const Permission$FullFraction: int;
-const Permission$Zero: [PermissionComponent]int;
-axiom Permission$Zero[perm$R] == 0 && Permission$Zero[perm$N] == 0;
-const Permission$Full: [PermissionComponent]int;
-axiom Permission$Full[perm$R] == Permission$FullFraction && Permission$Full[perm$N] == 0;
+const Permission$denominator: real;
+axiom Permission$denominator == 1.0;
+const Permission$FullFraction: real;
+const Permission$Zero: [PermissionComponent]real;
+axiom Permission$Zero[perm$R] == 0.0 && Permission$Zero[perm$N] == 0.0;
+const Permission$Full: [PermissionComponent]real;
+axiom Permission$Full[perm$R] == Permission$FullFraction && Permission$Full[perm$N] == 0.0;
const ZeroMask: MaskType;
-axiom (forall<T> o: ref, f: Field T, pc: PermissionComponent :: ZeroMask[o,f][pc] == 0);
+axiom (forall<T> o: ref, f: Field T, pc: PermissionComponent :: ZeroMask[o,f][pc] == 0.0);
+const ZeroPMask: PMaskType;
+axiom (forall<T> o: ref, f: Field T :: ZeroPMask[o,f] == false);
axiom IsGoodMask(ZeroMask);
const unique joinable: Field int;
axiom NonPredicateField(joinable);
const unique token#t: TypeName;
-const unique forkK: Field int;
+const unique forkK: Field real;
axiom NonPredicateField(forkK);
-const channelK: int;
-const monitorK: int;
-const predicateK: int;"""
+const channelK: real;
+const monitorK: real;
+const predicateK: real;"""
}
object PercentageStandardPL extends PreludeComponent {
val text = """
-axiom (0 < channelK && 1000*channelK < Permission$denominator);
-axiom (0 < monitorK && 1000*monitorK < Permission$denominator);
-axiom (0 < predicateK && 1000*predicateK < Permission$denominator);
-axiom Permission$FullFraction == 100*Permission$denominator;
+axiom Permission$FullFraction == 1.0;
+axiom 0.0 < channelK && 1000.0*channelK < 0.01;
+axiom 0.0 < monitorK && 1000.0*monitorK < 0.01;
+axiom 0.0 < predicateK && 1000.0*predicateK < 0.01;
axiom predicateK == channelK && channelK == monitorK;"""
}
-object PercentageFixedDenominatorPL extends PreludeComponent {
- val text = """
-axiom Permission$denominator == 100000000000;"""
-}
object PercentageFunctionPL extends PreludeComponent {
val text = """
-function Fractions(n: int) returns (int)
+function Fractions(n: int) returns (real)
{
- n * Permission$denominator
-}
-axiom (forall x,y: int :: 0 <= x && x <= y ==> Fractions(x) <= Fractions(y));
-
-axiom Permission$FullFraction == Fractions(100);
-axiom 0 < channelK && 1000*channelK < Fractions(1);
-axiom 0 < monitorK && 1000*monitorK < Fractions(1);
-axiom 0 < predicateK && 1000*predicateK < Fractions(1);
-axiom predicateK == channelK && channelK == monitorK;"""
+ n / 100.0
}
-object PercentageUninterpretedFunctionPL extends PreludeComponent {
- val text = """
-function Fractions(n: int) returns (int);
-function Fractions'(n: int) returns (int);
-axiom (forall x: int :: { Fractions(x) } Fractions(x) == Fractions'(x));
-axiom (forall x,y: int :: 0 <= x && x <= y ==> Fractions'(x) <= Fractions'(y));
-axiom (forall x,y: int :: { Fractions(x), Fractions(y) } Fractions(x) + Fractions(y) == Fractions'(x+y));
+axiom (forall x,y: int :: 0.0 <= real(x) && real(x) <= real(y) ==> Fractions(x) <= Fractions(y));
axiom Permission$FullFraction == Fractions(100);
-axiom 0 < channelK && 1000*channelK < Fractions(1);
-axiom 0 < monitorK && 1000*monitorK < Fractions(1);
-axiom 0 < predicateK && 1000*predicateK < Fractions(1);
+axiom 0.0 < channelK && 1000.0*channelK < Fractions(1);
+axiom 0.0 < monitorK && 1000.0*monitorK < Fractions(1);
+axiom 0.0 < predicateK && 1000.0*predicateK < Fractions(1);
axiom predicateK == channelK && channelK == monitorK;"""
}
object CreditsAndMuPL extends PreludeComponent {
- val text = """
+ def text = {
+ val base = """
var Credits: CreditsType;
function combine(PartialHeapType, PartialHeapType) returns (PartialHeapType);
@@ -147,6 +140,7 @@ const CurrentModule: ModuleName;
type TypeName;
function dtype(ref) returns (TypeName);
const CanAssumeFunctionDefs: bool;
+const FunctionContextHeight: int;
type Mu;
const unique mu: Field Mu;
@@ -186,6 +180,11 @@ function IsGoodInhaleState(ih: HeapType, h: HeapType,
(forall o: ref :: { h[o, held] } (0<h[o, held]) ==> ih[o, mu] == h[o, mu]) &&
(forall o: ref :: { h[o, rdheld] } h[o, rdheld] ==> ih[o, mu] == h[o, mu])
}
+function IsGoodExhalePredicateState(eh: HeapType, h: HeapType, pm: PMaskType) returns (bool)
+{
+ (forall<T> o: ref, f: Field T :: { eh[o, f] } pm[o, f] ==> eh[o, f] == h[o, f])
+}
+function predicateMaskField<T>(f: Field T): Field PMaskType;
function IsGoodExhaleState(eh: HeapType, h: HeapType,
m: MaskType, sm: MaskType) returns (bool)
{
@@ -196,8 +195,16 @@ function IsGoodExhaleState(eh: HeapType, h: HeapType,
(forall o: ref :: { h[o, rdheld] } h[o, rdheld] ==> eh[o, mu] == h[o, mu]) &&
(forall o: ref :: { h[o, forkK] } { eh[o, forkK] } h[o, forkK] == eh[o, forkK]) &&
(forall o: ref :: { h[o, held] } { eh[o, held] } h[o, held] == eh[o, held]) &&
- (forall o: ref, f: Field int :: { eh[o, f], PredicateField(f) } PredicateField(f) ==> h[o, f] <= eh[o, f])
-}"""
+ (forall o: ref, f: Field int :: { eh[o, f], PredicateField(f) } PredicateField(f) ==> h[o, f] <= eh[o, f]) &&
+ (forall o: ref, f: Field int :: { h[o, predicateMaskField(f)], PredicateField(f) } { eh[o, predicateMaskField(f)], PredicateField(f) } { m[o, predicateMaskField(f)], PredicateField(f) } """
+ val triggers = (TranslatorPrelude.predicates map (x => "{ #"+x.FullName+"#trigger(o), PredicateField(f) }")).mkString(" ")
+ val rest = """ PredicateField(f) && CanRead(m, sm, o, f) ==>
+ (forall<T> o2: ref, f2: Field T :: { h[o2, f2] } { eh[o2, f2] } { m[o2, f2] } h[o, predicateMaskField(f)][o2, f2] ==> eh[o2, f2] == h[o2, f2])) &&
+ (forall o: ref, f: Field int :: { PredicateField(f), eh[o, predicateMaskField(f)] } PredicateField(f) && CanRead(m, sm, o, f) ==> eh[o, predicateMaskField(f)] == h[o, predicateMaskField(f)])
+}
+ """
+ base + triggers + rest
+ }
}
object PermissionFunctionsAndAxiomsPL extends PreludeComponent {
val text = """
@@ -207,50 +214,49 @@ object PermissionFunctionsAndAxiomsPL extends PreludeComponent {
function {:expand false} CanRead<T>(m: MaskType, sm: MaskType, obj: ref, f: Field T) returns (bool)
{
- 0 < m[obj,f][perm$R] || 0 < m[obj,f][perm$N] ||
- 0 < sm[obj,f][perm$R] || 0 < sm[obj,f][perm$N]
+ 0.0 < m[obj,f][perm$R] || 0.0 < m[obj,f][perm$N]
}
function {:expand false} CanReadForSure<T>(m: MaskType, obj: ref, f: Field T) returns (bool)
{
- 0 < m[obj,f][perm$R] || 0 < m[obj,f][perm$N]
+ 0.0 < m[obj,f][perm$R] || 0.0 < m[obj,f][perm$N]
}
function {:expand false} CanWrite<T>(m: MaskType, obj: ref, f: Field T) returns (bool)
{
- m[obj,f][perm$R] == Permission$FullFraction && m[obj,f][perm$N] == 0
+ m[obj,f][perm$R] == Permission$FullFraction && m[obj,f][perm$N] == 0.0
}
function {:expand true} IsGoodMask(m: MaskType) returns (bool)
{
(forall<T> o: ref, f: Field T ::
- 0 <= m[o,f][perm$R] &&
+ 0.0 <= m[o,f][perm$R] &&
(NonPredicateField(f) ==>
(m[o,f][perm$R]<=Permission$FullFraction &&
- (0 < m[o,f][perm$N] ==> m[o,f][perm$R] < Permission$FullFraction))) &&
- (m[o,f][perm$N] < 0 ==> 0 < m[o,f][perm$R]))
+ (0.0 < m[o,f][perm$N] ==> m[o,f][perm$R] < Permission$FullFraction))) &&
+ (m[o,f][perm$N] < 0.0 ==> 0.0 < m[o,f][perm$R]))
}
axiom (forall h: HeapType, m, sm: MaskType, o: ref, q: ref :: {wf(h, m, sm), h[o, mu], h[q, mu]} wf(h, m, sm) && o!=q && (0 < h[o, held] || h[o, rdheld]) && (0 < h[q, held] || h[q, rdheld]) ==> h[o, mu] != h[q, mu]);
-function DecPerm<T>(m: MaskType, o: ref, f: Field T, howMuch: int) returns (MaskType);
+function DecPerm<T>(m: MaskType, o: ref, f: Field T, howMuch: real) returns (MaskType);
-axiom (forall<T,U> m: MaskType, o: ref, f: Field T, howMuch: int, q: ref, g: Field U :: {DecPerm(m, o, f, howMuch)[q, g][perm$R]}
+axiom (forall<T,U> m: MaskType, o: ref, f: Field T, howMuch: real, q: ref, g: Field U :: {DecPerm(m, o, f, howMuch)[q, g][perm$R]}
DecPerm(m, o, f, howMuch)[q, g][perm$R] == ite(o==q && f ==g, m[q, g][perm$R] - howMuch, m[q, g][perm$R])
);
-function DecEpsilons<T>(m: MaskType, o: ref, f: Field T, howMuch: int) returns (MaskType);
+function DecEpsilons<T>(m: MaskType, o: ref, f: Field T, howMuch: real) returns (MaskType);
-axiom (forall<T,U> m: MaskType, o: ref, f: Field T, howMuch: int, q: ref, g: Field U :: {DecPerm(m, o, f, howMuch)[q, g][perm$N]}
+axiom (forall<T,U> m: MaskType, o: ref, f: Field T, howMuch: real, q: ref, g: Field U :: {DecPerm(m, o, f, howMuch)[q, g][perm$N]}
DecEpsilons(m, o, f, howMuch)[q, g][perm$N] == ite(o==q && f ==g, m[q, g][perm$N] - howMuch, m[q, g][perm$N])
);
-function IncPerm<T>(m: MaskType, o: ref, f: Field T, howMuch: int) returns (MaskType);
+function IncPerm<T>(m: MaskType, o: ref, f: Field T, howMuch: real) returns (MaskType);
-axiom (forall<T,U> m: MaskType, o: ref, f: Field T, howMuch: int, q: ref, g: Field U :: {IncPerm(m, o, f, howMuch)[q, g][perm$R]}
+axiom (forall<T,U> m: MaskType, o: ref, f: Field T, howMuch: real, q: ref, g: Field U :: {IncPerm(m, o, f, howMuch)[q, g][perm$R]}
IncPerm(m, o, f, howMuch)[q, g][perm$R] == ite(o==q && f ==g, m[q, g][perm$R] + howMuch, m[q, g][perm$R])
);
-function IncEpsilons<T>(m: MaskType, o: ref, f: Field T, howMuch: int) returns (MaskType);
+function IncEpsilons<T>(m: MaskType, o: ref, f: Field T, howMuch: real) returns (MaskType);
-axiom (forall<T,U> m: MaskType, o: ref, f: Field T, howMuch: int, q: ref, g: Field U :: {IncPerm(m, o, f, howMuch)[q, g][perm$N]}
+axiom (forall<T,U> m: MaskType, o: ref, f: Field T, howMuch: real, q: ref, g: Field U :: {IncPerm(m, o, f, howMuch)[q, g][perm$N]}
IncEpsilons(m, o, f, howMuch)[q, g][perm$N] == ite(o==q && f ==g, m[q, g][perm$N] + howMuch, m[q, g][perm$N])
);
@@ -268,7 +274,7 @@ function Call$Args(int) returns (ArgSeq);
type ArgSeq = <T>[int]T;
function EmptyMask(m: MaskType) returns (bool);
-axiom (forall m: MaskType :: {EmptyMask(m)} EmptyMask(m) <==> (forall<T> o: ref, f: Field T :: NonPredicateField(f) ==> m[o, f][perm$R]<=0 && m[o, f][perm$N]<=0));
+axiom (forall m: MaskType :: {EmptyMask(m)} EmptyMask(m) <==> (forall<T> o: ref, f: Field T :: NonPredicateField(f) ==> m[o, f][perm$R]<=0.0 && m[o, f][perm$N]<=0.0));
const ZeroCredits: CreditsType;
axiom (forall o: ref :: ZeroCredits[o] == 0);
@@ -280,6 +286,16 @@ function PredicateField<T>(f: Field T) returns (bool);
axiom (forall<T> f: Field T :: NonPredicateField(f) ==> ! PredicateField(f));
axiom (forall<T> f: Field T :: PredicateField(f) ==> ! NonPredicateField(f));
+// function for recording enclosure of one predicate instance in another
+function #predicateInside#(x:ref, p: Field (int), v:int, y:ref, q:Field (int), w : int) returns (bool);
+
+// transitivity for #predicateInside#
+axiom (forall x:ref, p: Field (int), v:int, y:ref, q:Field (int), w : int, z:ref, r:Field(int),u:int :: {#predicateInside#(x,p,v,y,q,w), #predicateInside#(y,q,w,z,r,u)} #predicateInside#(x,p,v,y,q,w) && #predicateInside#(y,q,w,z,r,u) ==> #predicateInside#(x,p,v,z,r,u));
+
+// knowledge that two identical instances of the same predicate cannot be inside each other
+axiom (forall x:ref, p: Field (int), v:int, y:ref, w:int :: {#predicateInside#(x,p,v,y,p,w)} #predicateInside#(x,p,v,y,p,w) ==> x!=y);
+
+
function submask(m1: MaskType, m2: MaskType) returns (bool);
axiom (forall m1: MaskType, m2: MaskType :: {submask(m1, m2)}
@@ -296,23 +312,6 @@ function ite<T>(bool, T, T) returns (T);
axiom (forall<T> con: bool, a: T, b: T :: {ite(con, a, b)} con ==> ite(con, a, b) == a);
axiom (forall<T> con: bool, a: T, b: T :: {ite(con, a, b)} ! con ==> ite(con, a, b) == b);"""
}
-object ArithmeticPL extends PreludeComponent {
- val text = """
-// ---------------------------------------------------------------
-// -- Arithmetic -------------------------------------------------
-// ---------------------------------------------------------------
-
-// the connection between % and /
-axiom (forall x:int, y:int :: {x % y} {x / y} x % y == x - x / y * y);
-
-// sign of denominator determines sign of remainder
-axiom (forall x:int, y:int :: {x % y} 0 < y ==> 0 <= x % y && x % y < y);
-axiom (forall x:int, y:int :: {x % y} y < 0 ==> y < x % y && x % y <= 0);
-
-// the following axiom has some unfortunate matching, but it does state a property about % that
-// is sometime useful
-axiom (forall a: int, b: int, d: int :: { a % d, b % d } 2 <= d && a % d == b % d && a < b ==> a + d <= b);"""
-}
object StringPL extends PreludeComponent {
val text = """
// ---------------------------------------------------------------
diff --git a/Chalice/src/main/scala/Resolver.scala b/Chalice/src/main/scala/Resolver.scala
index dda5d989..5dc24662 100644
--- a/Chalice/src/main/scala/Resolver.scala
+++ b/Chalice/src/main/scala/Resolver.scala
@@ -19,9 +19,13 @@ object Resolver {
val currentMember: Member, val errors: ListBuffer[(Position,String)]) {
final def AddVariable(v: Variable): ProgramContext = new LProgramContext(v, this);
final def Error(pos: Position, msg: String) {errors += ((pos, msg))}
- final def SetClass(cl: Class): ProgramContext = new MProgramContext(cl, null, this)
+ final def SetClass(cl: Class): ProgramContext = new MProgramContext(cl, null, false, this)
final def SetMember(m: Member): ProgramContext = {
- var ctx:ProgramContext = new MProgramContext(currentClass, m, this)
+ val static = m match {
+ case f: Function => f.isStatic
+ case _ => false
+ }
+ var ctx:ProgramContext = new MProgramContext(currentClass, m, static, this)
m match {
case m: Method =>
assert(currentClass == m.Parent)
@@ -36,20 +40,30 @@ object Resolver {
}
ctx
}
+ final def AsNonStatic(): ProgramContext = new NSProgramContext(this)
def LookupVariable(id: String): Option[Variable] = None
def IsVariablePresent(vr: Variable): Boolean = false
-
+ def IsStatic: Boolean = false
+
private class LProgramContext(v: Variable, parent: ProgramContext) extends ProgramContext(parent.decls, parent.currentClass, parent.currentMember, errors) {
assert (v!=null)
override def LookupVariable(id: String): Option[Variable] =
if (id == v.id) Some(v) else parent.LookupVariable(id)
override def IsVariablePresent(vr: Variable): Boolean =
if (vr == v) true else parent.IsVariablePresent(vr)
+ override def IsStatic = parent.IsStatic
}
- private class MProgramContext(cl: Class, m: Member, parent: ProgramContext) extends ProgramContext(parent.decls, cl, m, errors) {
+ private class MProgramContext(cl: Class, m: Member, static: Boolean, parent: ProgramContext) extends ProgramContext(parent.decls, cl, m, errors) {
override def LookupVariable(id: String) = parent.LookupVariable(id)
override def IsVariablePresent(vr: Variable) = parent.IsVariablePresent(vr)
+ override def IsStatic: Boolean =
+ if (static) true else parent.IsStatic
+ }
+ private class NSProgramContext(parent: ProgramContext) extends ProgramContext(parent.decls, parent.currentClass, parent.currentMember, errors) {
+ override def LookupVariable(id: String) = parent.LookupVariable(id)
+ override def IsVariablePresent(vr: Variable) = parent.IsVariablePresent(vr)
+ override def IsStatic = false
}
}
@@ -244,6 +258,24 @@ object Resolver {
}
b
}
+ def hasAccessibilityPredicate(e: Expression) = {
+ var b = false
+ e visitOpt {
+ case _: PermissionExpr => b = true; false
+ case ma: MemberAccess => if (ma.isPredicate) { b = true; false } else { true }
+ case Unfolding(pred, e) => false
+ case _ => true
+ }
+ b
+ }
+ def hasUnfoldingExpression(e: Expression) = {
+ var b = false
+ e visit {
+ case Unfolding(pred, e) => b = true
+ case _ =>
+ }
+ b
+ }
spec foreach {
case p@Precondition(e) =>
ResolveExpr(e, context, false, true)(false)
@@ -251,6 +283,9 @@ object Resolver {
case p@Postcondition(e) =>
ResolveExpr(e, context, false, true)(false)
if (hasCredit(e)) context.Error(p.pos, "the specification of functions cannot contain credit expressions")
+ if (hasAccessibilityPredicate(e)) context.Error(p.pos, "the postcondition of functions cannot contain accessibility predicates (permissions are returned automatically)")
+ // The following check is necessary, because the postcondition axiom has the limited function as a trigger. If we were to allow unfolding expressions, then this might introduce a matching loop. Since we don't know of any cases where one would use an unfolding expression in the postcondition, we forbid it here.
+ if (hasUnfoldingExpression(e)) context.Error(p.pos, "the postcondition of functions cannot contain unfolding expressions at the moment")
case lc : LockChange => context.Error(lc.pos, "lockchange not allowed on function")
}
@@ -275,10 +310,13 @@ object Resolver {
}
}
- // fill in SCC for recursive functions
- val (_, h) = calls.computeSCC;
+ // fill in SCC and height for recursive functions
+ val (callGraphCondensation, h) = calls.computeSCC;
+ val callGraphTopoSort = callGraphCondensation.computeTopologicalSort.reverse
h.keys foreach {f:Function =>
f.SCC = h(f);
+ f.height = callGraphTopoSort.indexOf(h(f))
+ assert(f.height >= 0)
assert(f.SCC contains f);
if (h(f).size > 1)
f.isRecursive = true;
@@ -939,7 +977,11 @@ object Resolver {
context.LookupVariable(id) match {
case None => context.Error(ve.pos, "undefined local variable " + id); ve.typ = IntClass
case Some(v) => ve.Resolve(v) }
- case v:ThisExpr => v.typ = context.currentClass
+ case v:ThisExpr =>
+ v.typ = context.currentClass
+ if (context.IsStatic) {
+ context.Error(v.pos, "Accessing non-static member not allowed in static context.")
+ }
case sel @ MemberAccess(e, id) =>
ResolveExpr(e, context, twoStateContext, false)
var typ: Class = IntClass
@@ -1011,14 +1053,15 @@ object Resolver {
case ite@IfThenElse(con, then, els) =>
ResolveExpr(con, context, twoStateContext, false); ResolveExpr(then, context, twoStateContext, specContext); ResolveExpr(els, context, twoStateContext, specContext);
if (!con.typ.IsBool) context.Error(con.pos, "condition of if-then-else expression must be a boolean");
- if (! canAssign(then.typ, els.typ)) context.Error(ite.pos, "the then and else branch of an if-then-else expression must have compatible types");
+ if (!canAssign(then.typ, els.typ) && !canAssign(els.typ, then.typ)) context.Error(ite.pos, "the then and else branch of an if-then-else expression must have compatible types");
ite.typ = then.typ;
case expr@ Not(e) =>
ResolveExpr(e, context, twoStateContext, false)
if (!e.typ.IsBool) context.Error(expr.pos, "not-expression requires boolean operand")
expr.typ = BoolClass
case appl@FunctionApplication(obj, id, args) =>
- ResolveExpr(obj, context, twoStateContext, false);
+ // HACK: allow non-static access for receiver
+ ResolveExpr(obj, context.AsNonStatic(), twoStateContext, false);
args foreach { arg => ResolveExpr(arg, context, twoStateContext, false)};
// lookup function
appl.typ = IntClass
diff --git a/Chalice/src/main/scala/SmokeTest.scala b/Chalice/src/main/scala/SmokeTest.scala
index f317f24c..bd733ee6 100644
--- a/Chalice/src/main/scala/SmokeTest.scala
+++ b/Chalice/src/main/scala/SmokeTest.scala
@@ -76,7 +76,7 @@ object SmokeTest {
case None => ""
case Some((verified,errors)) =>
realErrors = errors-smokeErrors.size
- "Boogie program verifier finished with " + realErrors + " errors and " + smokeTestWarnings + " smoke test warnings."
+ "Boogie program verifier finished with " + realErrors + " errors and " + smokeTestWarnings + " smoke test warnings"
})
verificationResult +
diff --git a/Chalice/src/main/scala/Translator.scala b/Chalice/src/main/scala/Translator.scala
index 94d44d9e..60163a1a 100644
--- a/Chalice/src/main/scala/Translator.scala
+++ b/Chalice/src/main/scala/Translator.scala
@@ -79,8 +79,8 @@ class Translator {
def translateWhereClause(ch: Channel): List[Decl] = {
// pick new k
- val (whereKV, whereK) = Boogie.NewBVar("whereK", tint, true)
- val whereKStmts = BLocal(whereKV) :: bassume(0 < whereK && 1000*whereK < permissionOnePercent)
+ val (whereKV, whereK) = Boogie.NewBVar("whereK", treal, true)
+ val whereKStmts = BLocal(whereKV) :: bassume(0.0 < whereK && 1000.0*whereK < permissionOnePercent)
// check definedness of where clause
Proc(ch.channelId + "$whereClause$checkDefinedness",
@@ -111,8 +111,8 @@ class Translator {
val (lkV, lk) = NewBVar("lk", tref, true);
// pick new k
- val (methodKV, methodK) = Boogie.NewBVar("methodK", tint, true)
- val methodKStmts = BLocal(methodKV) :: bassume(0 < methodK && 1000*methodK < permissionOnePercent)
+ val (methodKV, methodK) = Boogie.NewBVar("methodK", treal, true)
+ val methodKStmts = BLocal(methodKV) :: bassume(0.0 < methodK && 1000.0*methodK < permissionOnePercent)
val oldTranslator = new ExpressionTranslator(Globals(h1, m1, sm1, c1), Globals(h0, m0, sm0, c0), currentClass);
Proc(currentClass.id + "$monitorinvariant$checkDefinedness",
@@ -164,19 +164,33 @@ class Translator {
etran = etran.CheckTermination(false);
// pick new k
- val (functionKV, functionK) = Boogie.NewBVar("functionK", tint, true)
- val functionKStmts = BLocal(functionKV) :: bassume(0 < functionK && 1000*functionK < permissionOnePercent)
+ val (functionKV, functionK) = Boogie.NewBVar("functionK", treal, true)
+ val functionKStmts = BLocal(functionKV) :: bassume(0.0 < functionK && 1000.0*functionK < permissionOnePercent)
// Boogie function that represents the Chalice function
- Boogie.Function(functionName(f), BVar("heap", theap) :: BVar("this", tref) :: (f.ins map Variable2BVar), BVar("$myresult", f.out.typ)) ::
+ {
+ val bIns = if (f.isStatic) {
+ BVar("heap", theap) :: (f.ins map Variable2BVar)
+ } else {
+ BVar("heap", theap) :: BVar("this", tref) :: (f.ins map Variable2BVar)
+ }
+ Boogie.Function(functionName(f), bIns, BVar("$myresult", f.out.typ))
+ } ::
// check definedness of the function's precondition and body
- Proc(f.FullName + "$checkDefinedness",
- NewBVarWhere("this", new Type(currentClass)) :: (f.ins map {i => Variable2BVarWhere(i)}),
+ Proc(f.FullName + "$checkDefinedness",
+ {
+ val insVar = f.ins map {i => Variable2BVarWhere(i)}
+ if (!f.isStatic) {
+ NewBVarWhere("this", new Type(currentClass)) :: insVar
+ } else {
+ insVar
+ }
+ },
Nil,
GlobalNames,
- DefaultPrecondition(),
+ DefaultPrecondition(f.isStatic),
functionKStmts :::
- //bassume(CanAssumeFunctionDefs) ::
+ bassume(FunctionContextHeight ==@ f.height) ::
DefinePreInitialState :::
// check definedness of the precondition
InhaleWithChecking(Preconditions(f.spec) map { p => (if(0 < Chalice.defaults) UnfoldPredicatesWithReceiverThis(p) else p)}, "precondition", functionK) :::
@@ -189,6 +203,19 @@ class Translator {
// check definedness of function body
checkBody :::
(f.definition match {case Some(e) => BLocal(myresult) :: (Boogie.VarExpr("result") := etran.Tr(e)); case None => Nil}) :::
+ // assume canCall for all recursive calls
+ {
+ var b: Expr = true
+ f.definition match {
+ case Some(e) => e transform {
+ case app @ FunctionApplication(obj, id, args) if id == f.Id =>
+ b = b && FunctionApp(functionName(f) + "#canCall", (obj :: args) map etran.Tr); None
+ case _ => None
+ }
+ case _ =>
+ }
+ bassume(b) :: Nil
+ } :::
// check that postcondition holds
ExhaleWithChecking(Postconditions(f.spec) map { post => ((if(0 < Chalice.defaults) UnfoldPredicatesWithReceiverThis(post) else post),
ErrorMessage(f.pos, "Postcondition at " + post.pos + " might not hold."))}, "function postcondition", functionK, true)) ::
@@ -206,21 +233,35 @@ class Translator {
def definitionAxiom(f: Function, definition: Expression): List[Decl] = {
val inArgs = (f.ins map {i => Boogie.VarExpr(i.UniqueName)})
val thisArg = VarExpr("this")
- val args = thisArg :: inArgs;
+ val args = if (f.isStatic) inArgs else thisArg :: inArgs;
+
+ /////
- val formalsNoMask = BVar(HeapName, theap) :: BVar("this", tref) :: (f.ins map Variable2BVar)
+ val formalsNoHeapNoMask = if (f.isStatic) {
+ (f.ins map Variable2BVar)
+ } else {
+ BVar("this", tref) :: (f.ins map Variable2BVar)
+ }
+
+ val formalsNoMask = BVar(HeapName, theap) :: formalsNoHeapNoMask
val formals = BVar(MaskName, tmask) :: BVar(SecMaskName, tmask) :: formalsNoMask
val applyF = FunctionApp(functionName(f), List(etran.Heap) ::: args);
val limitedApplyF = FunctionApp(functionName(f) + "#limited", List(etran.Heap) ::: args)
+ /////
+ val limitedFTrigger = FunctionApp(functionName(f) + "#limited#trigger", args)
+
val pre = Preconditions(f.spec).foldLeft(BoolLiteral(true): Expression)({ (a, b) => And(a, b) });
val wellformed = wf(VarExpr(HeapName), VarExpr(MaskName), VarExpr(SecMaskName))
val triggers = f.dependentPredicates map (p => new Trigger(List(limitedApplyF, wellformed, FunctionApp("#" + p.FullName+"#trigger", thisArg :: Nil))))
+ /////
+ val newTriggers = new Trigger(List(limitedFTrigger, wellformed) ::: (f.dependentPredicates map (p => FunctionApp("#" + p.FullName+"#trigger", thisArg :: Nil))))
/** Limit application of the function by introducing a second (limited) function */
val body = etran.Tr(
- if (f.isRecursive && ! f.isUnlimited) {
+ if (true) { // used to be: if (f.isRecursive && ! f.isUnlimited) ... but now we treat all functions uniformly
val limited = Map() ++ (f.SCC zip (f.SCC map {f =>
val result = Function(f.id + "#limited", f.ins, f.out, f.spec, None);
+ result.isStatic = f.isStatic
result.Parent = f.Parent;
result;
}));
@@ -237,21 +278,28 @@ class Translator {
}
);
+ Boogie.Function(functionName(f) + "#canCall", formalsNoHeapNoMask, BVar("$myresult", tbool)) ::
/* axiom (forall h: HeapType, m, sm: MaskType, this: ref, x_1: t_1, ..., x_n: t_n ::
wf(h, m, sm) && CurrentModule == module#C ==> #C.f(h, m, this, x_1, ..., x_n) == tr(body))
*/
Axiom(new Boogie.Forall(Nil,
- formals, List(new Trigger(List(applyF,wellformed))),
+ formals, newTriggers :: List(new Trigger(List(applyF,wellformed))) ,
(wellformed && (CurrentModule ==@ ModuleName(currentClass)) && etran.TrAll(pre))
==>
(applyF ==@ body))) ::
- (if (f.isRecursive)
+ (if (true)
+ // used to be: (if (f.isRecursive) ... but now we treat all functions uniformly
// define the limited function (even for unlimited function since its SCC might have limited functions)
Boogie.Function(functionName(f) + "#limited", formalsNoMask, BVar("$myresult", f.out.typ)) ::
Axiom(new Boogie.Forall(Nil, formals,
- new Trigger(List(applyF,wellformed)) :: triggers,
+ new Trigger(List(applyF,wellformed)) :: Nil,
+ // new Trigger(List(applyF,wellformed)) :: triggers, // commented, as secondary patterns seem not to be working
(wellformed ==> (applyF ==@ limitedApplyF)))) ::
- Nil
+ Boogie.Function(functionName(f) + "#limited#trigger", formalsNoHeapNoMask, BVar("$myresult", tbool)) ::
+ Axiom(new Boogie.Forall(Nil, formals,
+ List(new Trigger(List(limitedApplyF,wellformed))),
+ (wellformed ==> limitedFTrigger))) ::
+ Nil ///// above
else
Nil)
}
@@ -271,18 +319,29 @@ class Translator {
val inArgs = (f.ins map {i => Boogie.VarExpr(i.UniqueName)});
val frameFunctionName = "#" + functionName(f);
- val args = VarExpr("this") :: inArgs;
+ val args = if (!f.isStatic) VarExpr("this") :: inArgs else inArgs;
val applyF = FunctionApp(functionName(f) + (if (f.isRecursive) "#limited" else ""), List(etran.Heap) ::: args);
val applyFrameFunction = FunctionApp(frameFunctionName, partialHeap :: args)
val wellformed = wf(VarExpr(HeapName), VarExpr(MaskName), VarExpr(SecMaskName))
- Boogie.Function(frameFunctionName, Boogie.BVar("state", tpartialheap) :: Boogie.BVar("this", tref) :: (f.ins map Variable2BVar), new BVar("$myresult", f.out.typ)) ::
- Axiom(new Boogie.Forall(
- BVar(HeapName, theap) :: BVar(MaskName, tmask) :: BVar(SecMaskName, tmask) :: BVar("this", tref) :: (f.ins map Variable2BVar),
- new Trigger(List(applyF, wellformed)),
- (wellformed && CanAssumeFunctionDefs)
- ==>
- (applyF ==@ applyFrameFunction))
+ if (!f.isStatic) (
+ Boogie.Function(frameFunctionName, Boogie.BVar("state", tpartialheap) :: Boogie.BVar("this", tref) :: (f.ins map Variable2BVar), new BVar("$myresult", f.out.typ)) ::
+ Axiom(new Boogie.Forall(
+ BVar(HeapName, theap) :: BVar(MaskName, tmask) :: BVar(SecMaskName, tmask) :: BVar("this", tref) :: (f.ins map Variable2BVar),
+ new Trigger(List(applyF, wellformed)),
+ (wellformed)
+ ==>
+ (applyF ==@ applyFrameFunction))
+ )
+ ) else (
+ Boogie.Function(frameFunctionName, Boogie.BVar("state", tpartialheap) :: (f.ins map Variable2BVar), new BVar("$myresult", f.out.typ)) ::
+ Axiom(new Boogie.Forall(
+ BVar(HeapName, theap) :: BVar(MaskName, tmask) :: BVar(SecMaskName, tmask) :: (f.ins map Variable2BVar),
+ new Trigger(List(applyF, wellformed)),
+ (wellformed)
+ ==>
+ (applyF ==@ applyFrameFunction))
+ )
)
} else {
// Encoding with universal quantification over two heaps
@@ -290,7 +349,8 @@ class Translator {
wf(h1,m1,sm1) && wf(h2,m2,sm1) && functionDependenciesEqual(h1, h2, #C.f) ==>
#C.f(h1, m1, sm1, this, x_1, ..., x_n) == #C.f(h2, m2, sm2, this, x_1, ..., x_n)
*/
- var args = VarExpr("this") :: (f.ins map {i => Boogie.VarExpr(i.UniqueName)});
+ var args = if (!f.isStatic) VarExpr("this") :: (f.ins map {i => Boogie.VarExpr(i.UniqueName)})
+ else (f.ins map {i => Boogie.VarExpr(i.UniqueName)})
// create two heaps
val (globals1V, globals1) = etran.FreshGlobals("a"); val etran1 = new ExpressionTranslator(globals1, currentClass);
@@ -301,33 +361,44 @@ class Translator {
val apply2 = FunctionApp(functionName(f), etran2.Heap :: args)
val wellformed1 = wf(etran1.Heap, etran1.Mask, etran1.SecMask)
val wellformed2 = wf(etran2.Heap, etran2.Mask, etran2.SecMask)
-
- Axiom(new Boogie.Forall(
- heap1 :: heap2 :: mask1 :: mask2 :: secmask1 :: secmask2 :: BVar("this", tref) :: (f.ins map Variable2BVar),
- new Trigger(List(apply1, apply2, wellformed1, wellformed2)),
- (wellformed1 && wellformed2 && functionDependenciesEqual(pre, etran1, etran2) && CanAssumeFunctionDefs)
- ==>
- (apply1 ==@ apply2)
- ))
+
+ if (!f.isStatic) (
+ Axiom(new Boogie.Forall(
+ heap1 :: heap2 :: mask1 :: mask2 :: secmask1 :: secmask2 :: BVar("this", tref) :: (f.ins map Variable2BVar),
+ new Trigger(List(apply1, apply2, wellformed1, wellformed2)),
+ (wellformed1 && wellformed2 && functionDependenciesEqual(pre, etran1, etran2))
+ ==>
+ (apply1 ==@ apply2)
+ ))
+ ) else (
+ Axiom(new Boogie.Forall(
+ heap1 :: heap2 :: mask1 :: mask2 :: secmask1 :: secmask2 :: (f.ins map Variable2BVar),
+ new Trigger(List(apply1, apply2, wellformed1, wellformed2)),
+ (wellformed1 && wellformed2 && functionDependenciesEqual(pre, etran1, etran2))
+ ==>
+ (apply1 ==@ apply2)
+ ))
+ )
}
}
def postconditionAxiom(f: Function): List[Decl] = {
/* axiom (forall h: HeapType, m, sm: MaskType, this: ref, x_1: t_1, ..., x_n: t_n ::
- wf(h, m, sm) && CanAssumeFunctionDefs ==> Q[#C.f(h, m, this, x_1, ..., x_n)/result]
+ wf(h, m, sm) && (CanAssumeFunctionDefs || f.height < FunctionContextHeight) ==> Q[#C.f(h, m, this, x_1, ..., x_n)/result]
*/
val inArgs = (f.ins map {i => Boogie.VarExpr(i.UniqueName)});
val myresult = Boogie.BVar("result", f.out.typ);
val args = VarExpr("this") :: inArgs;
- val applyF = FunctionApp(functionName(f), List(VarExpr(HeapName)) ::: args)
+ val applyFLimited = FunctionApp(functionName(f)+"#limited", List(VarExpr(HeapName)) ::: args)
+ val canCall = FunctionApp(functionName(f) + "#canCall", args)
val wellformed = wf(VarExpr(HeapName), VarExpr(MaskName), VarExpr(SecMaskName))
//postcondition axioms
(Postconditions(f.spec) map { post : Expression =>
Axiom(new Boogie.Forall(
BVar(HeapName, theap) :: BVar(MaskName, tmask) :: BVar(SecMaskName, tmask) :: BVar("this", tref) :: (f.ins map Variable2BVar),
- new Trigger(List(applyF, wellformed)),
- (wellformed && CanAssumeFunctionDefs)
+ new Trigger(List(applyFLimited, wellformed)),
+ (wellformed && (CanAssumeFunctionDefs || f.height < FunctionContextHeight || canCall))
==>
etran.Tr(SubstResult(post, f.apply(ExplicitThisExpr(), f.ins map { arg => new VariableExpr(arg) })))
))
@@ -337,13 +408,15 @@ class Translator {
def translatePredicate(pred: Predicate): List[Decl] = {
// pick new k
- val (predicateKV, predicateK) = Boogie.NewBVar("predicateK", tint, true)
- val predicateKStmts = BLocal(predicateKV) :: bassume(0 < predicateK && 1000*predicateK < permissionOnePercent)
+ val (predicateKV, predicateK) = Boogie.NewBVar("predicateK", treal, true)
+ val predicateKStmts = BLocal(predicateKV) :: bassume(0.0 < predicateK && 1000.0*predicateK < permissionOnePercent)
// const unique class.name: HeapType;
Const(pred.FullName, true, FieldType(tint)) ::
- // axiom PredicateField(f);
+ Const(pred.FullName+"#m", true, FieldType(tpmask)) ::
Axiom(PredicateField(pred.FullName)) ::
+ // axiom PredicateField(f);
+ Axiom(FunctionApp("predicateMaskField", List(VarExpr(pred.FullName))) ==@ VarExpr(pred.FullName + "#m")) ::
// trigger function to unfold function definitions
Boogie.Function("#" + pred.FullName + "#trigger", BVar("this", tref) :: Nil, BVar("$myresult", tbool)) ::
// check definedness of predicate body
@@ -366,8 +439,8 @@ class Translator {
def translateMethod(method: Method): List[Decl] = {
// pick new k for this method, that represents the fraction for read permissions
- val (methodKV, methodK) = Boogie.NewBVar("methodK", tint, true)
- val methodKStmts = BLocal(methodKV) :: bassume(0 < methodK && 1000*methodK < permissionOnePercent)
+ val (methodKV, methodK) = Boogie.NewBVar("methodK", treal, true)
+ val methodKStmts = BLocal(methodKV) :: bassume(0.0 < methodK && 1000.0*methodK < permissionOnePercent)
// check definedness of the method contract
Proc(method.FullName + "$checkDefinedness",
@@ -427,8 +500,8 @@ class Translator {
val postCI = Postconditions(mt.refines.Spec).map(extractInv)
// pick new k for this method, that represents the fraction for read permissions
- val (methodKV, methodK) = Boogie.NewBVar("methodK", tint, true)
- val methodKStmts = BLocal(methodKV) :: bassume(0 < methodK && 1000*methodK < permissionOnePercent)
+ val (methodKV, methodK) = Boogie.NewBVar("methodK", treal, true)
+ val methodKStmts = BLocal(methodKV) :: bassume(0.0 < methodK && 1000.0*methodK < permissionOnePercent)
// check definedness of refinement specifications
Proc(mt.FullName + "$checkDefinedness",
@@ -476,10 +549,13 @@ class Translator {
new Boogie.Forall(chV, (ch ==@ bnull) || (0 <= new MapSelect(etran.Credits, ch)))
}
- def DefaultPrecondition() = {
- "requires this!=null;" ::
- "free requires wf(Heap, Mask, SecMask);" ::
- Nil
+ def DefaultPrecondition(isStatic: Boolean = false) = {
+ if (!isStatic) {
+ "requires this!=null;" ::
+ "free requires wf(Heap, Mask, SecMask);" :: Nil
+ } else {
+ "free requires wf(Heap, Mask, SecMask);" :: Nil
+ }
}
def DefinePreInitialState = {
@@ -487,11 +563,14 @@ class Translator {
(etran.Mask := ZeroMask) :: (etran.SecMask := ZeroMask) :: (etran.Credits := ZeroCredits)
}
def DefineInitialState = {
+ val (refV, ref) = Boogie.NewBVar("ref", tref, true)
+ val (pmaskV, pmask) = Boogie.NewBVar("pmask", FieldType(tpmask), true)
Comment("define initial state") ::
bassume(etran.Heap ==@ Boogie.Old(etran.Heap)) ::
bassume(etran.Mask ==@ Boogie.Old(etran.Mask)) ::
bassume(etran.SecMask ==@ Boogie.Old(etran.SecMask)) ::
- bassume(etran.Credits ==@ Boogie.Old(etran.Credits))
+ bassume(etran.Credits ==@ Boogie.Old(etran.Credits)) ::
+ bassume((etran.Heap.select(ref, pmask.id) ==@ ZeroPMask).forall(refV).forall(pmaskV))
}
/**********************************************************************
@@ -688,19 +767,20 @@ class Translator {
val (flagV, flag) = Boogie.NewBVar("predFlag", tbool, true)
// pick new k
- val (foldKV, foldK) = Boogie.NewBVar("foldK", tint, true)
+ val (foldKV, foldK) = Boogie.NewBVar("foldK", treal, true)
val stmts = Comment("fold") ::
functionTrigger(o, pred.predicate) ::
- BLocal(foldKV) :: bassume(0 < foldK && 1000*foldK < percentPermission(1) && 1000*foldK < methodK) ::
+ BLocal(foldKV) :: bassume(0.0 < foldK && 1000.0*foldK < percentPermission(1) && 1000.0*foldK < methodK) ::
isDefined(e) :::
isDefined(perm) :::
bassert(nonNull(o), s.pos, "The target of the fold statement might be null.") ::
// remove the definition from the current state, and replace by predicate itself
- etran.ExhaleAndTransferToSecMask(List((definition, ErrorMessage(s.pos, "Fold might fail because the definition of " + pred.predicate.FullName + " does not hold."))), "fold", foldK, false) :::
- Inhale(List(acc), "fold", foldK) :::
BLocal(receiverV) :: (receiver := o) ::
BLocal(versionV) :: (version := etran.Heap.select(o, pred.predicate.FullName)) ::
BLocal(flagV) :: (flag := true) ::
+ etran.ExhaleAndTransferToSecMask(o, pred.predicate, List((definition, ErrorMessage(s.pos, "Fold might fail because the definition of " + pred.predicate.FullName + " does not hold."))), "fold", foldK, false, receiver, pred.predicate.FullName, version) :::
+ Inhale(List(acc), "fold", foldK) :::
+ etran.keepFoldedLocations(definition, o, pred.predicate, etran.Mask, etran.Heap, etran.fpi.getFoldedPredicates(pred.predicate)) :::
bassume(wf(etran.Heap, etran.Mask, etran.SecMask))
// record folded predicate
@@ -712,15 +792,20 @@ class Translator {
val definition = scaleExpressionByPermission(SubstThis(DefinitionOf(pred.predicate), e), perm, unfld.pos)
// pick new k
- val (unfoldKV, unfoldK) = Boogie.NewBVar("unfoldK", tint, true)
+ val (unfoldKV, unfoldK) = Boogie.NewBVar("unfoldK", treal, true)
+ // record version of unfolded instance
+ val (receiverV, receiver) = Boogie.NewBVar("predRec", tref, true)
+ val (versionV, version) = Boogie.NewBVar("predVer", tint, true)
Comment("unfold") ::
functionTrigger(o, pred.predicate) ::
- BLocal(unfoldKV) :: bassume(0 < unfoldK && unfoldK < percentPermission(1) && 1000*unfoldK < methodK) ::
+ BLocal(receiverV) :: (receiver := o) ::
+ BLocal(versionV) :: (version := etran.Heap.select(o, pred.predicate.FullName)) ::
+ BLocal(unfoldKV) :: bassume(0.0 < unfoldK && unfoldK < percentPermission(1) && 1000.0*unfoldK < methodK) ::
isDefined(e) :::
bassert(nonNull(o), s.pos, "The target of the fold statement might be null.") ::
isDefined(perm) :::
ExhaleDuringUnfold(List((acc, ErrorMessage(s.pos, "unfold might fail because the predicate " + pred.predicate.FullName + " does not hold."))), "unfold", unfoldK, false) :::
- etran.Inhale(List(definition), "unfold", false, unfoldK)
+ etran.Inhale(List(definition), "unfold", false, unfoldK, receiver, pred.predicate.FullName, version)
case c@CallAsync(declaresLocal, token, obj, id, args) =>
val formalThisV = new Variable("this", new Type(c.m.Parent))
val formalThis = new VariableExpr(formalThisV)
@@ -737,9 +822,9 @@ class Translator {
val argsSeqLength = 1 + args.length;
// pick new k for this fork
- val (asyncMethodCallKV, asyncMethodCallK) = Boogie.NewBVar("asyncMethodCallK", tint, true)
+ val (asyncMethodCallKV, asyncMethodCallK) = Boogie.NewBVar("asyncMethodCallK", treal, true)
BLocal(asyncMethodCallKV) ::
- bassume(0 < asyncMethodCallK && 1000*asyncMethodCallK < percentPermission(1) && 1000*asyncMethodCallK < methodK) ::
+ bassume(0.0 < asyncMethodCallK && 1000.0*asyncMethodCallK < percentPermission(1) && 1000.0*asyncMethodCallK < methodK) ::
Comment("call " + id) ::
// declare the local variable, if needed
{ if (c.local == null)
@@ -773,8 +858,8 @@ class Translator {
BLocal(tokenV) :: Havoc(tokenId) :: bassume(nonNull(tokenId)) ::
// the following assumes help in proving that the token is fresh
bassume(etran.Heap.select(tokenId, "joinable") ==@ 0) ::
- bassume(new Boogie.MapSelect(etran.Mask, tokenId, "joinable", "perm$N")==@ 0) ::
- bassume(new Boogie.MapSelect(etran.Mask, tokenId, "joinable", "perm$R")==@ 0) ::
+ bassume(new Boogie.MapSelect(etran.Mask, tokenId, "joinable", "perm$N")==@ 0.0) ::
+ bassume(new Boogie.MapSelect(etran.Mask, tokenId, "joinable", "perm$R")==@ 0.0) ::
etran.IncPermission(tokenId, "joinable", permissionFull) :::
// create a fresh value for the joinable field
BLocal(asyncStateV) :: Boogie.Havoc(asyncState) :: bassume(asyncState !=@ 0) ::
@@ -804,12 +889,12 @@ class Translator {
val (preCallSecMaskV, preCallSecMask) = NewBVar("preCallSecMask", tmask, true);
val (preCallCreditsV, preCallCredits) = NewBVar("preCallCredits", tcredits, true);
val postEtran = new ExpressionTranslator(etran.globals, Globals(preCallHeap, preCallMask, preCallSecMask, preCallCredits), currentClass);
- val (asyncJoinKV, asyncJoinK) = Boogie.NewBVar("asyncJoinK", tint, true)
+ val (asyncJoinKV, asyncJoinK) = Boogie.NewBVar("asyncJoinK", treal, true)
Comment("join async") ::
// pick new k for this join
BLocal(asyncJoinKV) ::
- bassume(0 < asyncJoinK) ::
+ bassume(0.0 < asyncJoinK) ::
// try to use the same k as for the fork
bassume(asyncJoinK ==@ etran.Heap.select(token, forkK)) ::
// check that token is well-defined
@@ -1021,10 +1106,10 @@ class Translator {
val (preGlobalsV, preGlobals) = etran.FreshGlobals("pre")
// pick new k for the spec stmt
- val (specKV, specK) = Boogie.NewBVar("specStmtK", tint, true)
+ val (specKV, specK) = Boogie.NewBVar("specStmtK", treal, true)
BLocal(specKV) ::
- bassume(0 < specK && 1000*specK < percentPermission(1) && 1000*specK < methodK) ::
+ bassume(0.0 < specK && 1000.0*specK < percentPermission(1) && 1000.0*specK < methodK) ::
// declare new local variables
s.locals.flatMap(v => translateLocalVarDecl(v, true)) :::
Comment("spec statement") ::
@@ -1054,9 +1139,9 @@ class Translator {
val postEtran = etran.FromPreGlobals(preGlobals)
// pick new k for this method call
- val (methodCallKV, methodCallK) = Boogie.NewBVar("methodCallK", tint, true)
+ val (methodCallKV, methodCallK) = Boogie.NewBVar("methodCallK", treal, true)
BLocal(methodCallKV) ::
- bassume(0 < methodCallK && 1000*methodCallK < percentPermission(1) && 1000*methodCallK < methodK) ::
+ bassume(0.0 < methodCallK && 1000.0*methodCallK < percentPermission(1) && 1000.0*methodCallK < methodK) ::
Comment("call " + id) ::
// introduce formal parameters and pre-state globals
(for (v <- formalThisV :: formalInsV ::: formalOutsV) yield BLocal(Variable2BVarWhere(v))) :::
@@ -1104,13 +1189,13 @@ class Translator {
val oldLocks = lkchOld map (e => loopEtran.oldEtran.Tr(e))
val iterStartLocks = lkchIterStart map (e => iterStartEtran.oldEtran.Tr(e))
val newLocks = lkch map (e => loopEtran.Tr(e));
- val (whileKV, whileK) = Boogie.NewBVar("whileK", tint, true)
+ val (whileKV, whileK) = Boogie.NewBVar("whileK", treal, true)
val previousEtran = etran // save etran
Comment("while") ::
// pick new k for this method call
BLocal(whileKV) ::
- bassume(0 < whileK && 1000*whileK < percentPermission(1) && 1000*whileK < methodK) ::
+ bassume(0.0 < whileK && 1000.0*whileK < percentPermission(1) && 1000.0*whileK < methodK) ::
// save globals
BLocals(preLoopGlobalsV) :::
copyState(preLoopGlobals, loopEtran) :::
@@ -1341,7 +1426,7 @@ class Translator {
List(ttV),
List(Boogie.BVar("$o", tref), Boogie.BVar("$f", FieldType(tt))),
Nil,
- (o ==@ bnull) || ((new MapSelect(etran.Mask, o, f, "perm$R") ==@ 0) && (new MapSelect(etran.Mask, o, f, "perm$N") ==@ 0))
+ (o ==@ bnull) || ((new MapSelect(etran.Mask, o, f, "perm$R") ==@ 0.0) && (new MapSelect(etran.Mask, o, f, "perm$N") ==@ 0.0))
), pos, msg)
)
} else {
@@ -1475,11 +1560,21 @@ class FoldedPredicatesInfo {
foldedPredicates filter (fp => fp.predicate.FullName == predicate.FullName)
}
+ /** return a list of all folded predicates */
+ def getFoldedPredicates(): List[FoldedPredicate] = {
+ foldedPredicates
+ }
+
/** get an upper bound on the recursion depth when updating the secondary mask */
def getRecursionBound(predicate: Predicate): Int = {
foldedPredicates length
}
+ /** get an upper bound on the recursion depth when updating the secondary mask */
+ def getRecursionBound(): Int = {
+ foldedPredicates length
+ }
+
}
object FoldedPredicatesInfo {
def apply() = new FoldedPredicatesInfo()
@@ -1603,19 +1698,25 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
val tmpTranslator = new ExpressionTranslator(tmpGlobals, this.oldEtran.globals, currentClass);
// pick new k
- val (funcappKV, funcappK) = Boogie.NewBVar("funcappK", tint, true)
+ val (funcappKV, funcappK) = Boogie.NewBVar("funcappK", treal, true)
- // check definedness of receiver + arguments
- (obj :: args flatMap { arg => isDefined(arg) }) :::
+ // check definedness of receiver
+ (if (!func.f.isStatic) {
+ isDefined(obj)
+ } else Nil) :::
+ // check definedness of arguments
+ (args flatMap { arg => isDefined(arg) }) :::
// check that receiver is not null
- List(prove(nonNull(Tr(obj)), obj.pos, "Receiver might be null.")) :::
+ (if (!func.f.isStatic) {
+ List(prove(nonNull(Tr(obj)), obj.pos, "Receiver might be null."))
+ } else Nil) :::
// check precondition of the function by exhaling the precondition in tmpHeap/tmpMask/tmpCredits
Comment("check precondition of call") ::
- BLocal(funcappKV) :: bassume(0 < funcappK && 1000*funcappK < percentPermission(1)) ::
+ BLocal(funcappKV) :: bassume(0.0 < funcappK && 1000.0*funcappK < percentPermission(1)) ::
bassume(assumption) ::
BLocals(tmpGlobalsV) :::
copyState(tmpGlobals, this) :::
- tmpTranslator.Exhale(Preconditions(func.f.spec) map { pre=> (SubstVars(pre, obj, func.f.ins, args), ErrorMessage(func.pos, "Precondition at " + pre.pos + " might not hold."))},
+ tmpTranslator.Exhale(Preconditions(func.f.spec) map { pre=> (if (func.f.isStatic) SubstVars(pre, func.f.ins, args) else SubstVars(pre, obj, func.f.ins, args), ErrorMessage(func.pos, "Precondition at " + pre.pos + " might not hold."))},
"function call",
false, funcappK, false) :::
// size of the heap of callee must be strictly smaller than size of the heap of the caller
@@ -1630,11 +1731,16 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
val definition = scaleExpressionByPermission(SubstThis(DefinitionOf(pred.predicate), obj), perm, unfolding.pos)
// pick new k
- val (unfoldingKV, unfoldingK) = Boogie.NewBVar("unfoldingK", tint, true)
-
+ val (unfoldingKV, unfoldingK) = Boogie.NewBVar("unfoldingK", treal, true)
+ // record version of unfolded instance
+ val (receiverV, receiver) = Boogie.NewBVar("predRec", tref, true)
+ val (versionV, version) = Boogie.NewBVar("predVer", tint, true)
+
val res = Comment("unfolding") ::
- BLocal(unfoldingKV) :: bassume(0 < unfoldingK && 1000*unfoldingK < percentPermission(1)) ::
+ BLocal(unfoldingKV) :: bassume(0.0 < unfoldingK && 1000.0*unfoldingK < percentPermission(1)) ::
BLocal(flagV) :: (flag := true) ::
+ BLocal(receiverV) :: (receiver := o) ::
+ BLocal(versionV) :: (version := etran.Heap.select(o, pred.predicate.FullName)) :::
// check definedness
receiverOk ::: isDefined(perm) :::
// copy state into temporary variables
@@ -1643,16 +1749,16 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
// exhale the predicate
tmpTranslator.ExhaleDuringUnfold(List((acc, ErrorMessage(unfolding.pos, "Unfolding might fail."))), "unfolding", false, unfoldingK, false) :::
// inhale the definition of the predicate
- tmpTranslator.Inhale(List(definition), "unfolding", false, unfoldingK) :::
- // remove secondary permissions (if any), and add them again
- (if (isOldEtran) Nil else
- UpdateSecMaskDuringUnfold(pred.predicate, Tr(obj), Heap.select(Tr(obj), pred.predicate.FullName), perm, unfoldingK) :::
- TransferPermissionToSecMask(pred.predicate, obj, perm, unfolding.pos)) :::
+ tmpTranslator.Inhale(List(definition), "unfolding", false, unfoldingK, receiver, pred.predicate.FullName, version) :::
+ // update the predicate mask to indicate the predicates that are folded under 'pred'
+ (if (isOldEtran) Nil
+ else etran.keepFoldedLocations(definition, o, pred.predicate, etran.Mask, etran.Heap, etran.fpi.getFoldedPredicates(pred.predicate))) :::
// check definedness of e in state where the predicate is unfolded
- tmpTranslator.isDefined(e)
+ tmpTranslator.isDefined(e) :::
+ bassume(wf(etran.Heap, etran.Mask, etran.SecMask)) :: Nil
// record folded predicate
- val version = Heap.select(o, pred.predicate.FullName)
+ //val version = Heap.select(o, pred.predicate.FullName)
if (!isOldEtran) fpi.addFoldedPredicate(FoldedPredicate(pred.predicate, o, version, fpi.currentConditions, flag))
res
@@ -1729,140 +1835,356 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
* the expression and an expression translator as argument). The default
* behaviour is to translate only pure assertions (and throw and error otherwise).
*/
- def Tr(e: Expression): Boogie.Expr = Tr(e, (ee,et) => et.Tr(ee))
- def Tr(e: Expression, trrec: (Expression, ExpressionTranslator) => Expr): Boogie.Expr = {
- def trrecursive(e: Expression): Expr = trrec(e, this)
+ def Tr(e: Expression): Boogie.Expr = (Tr(e,false))._1
+ def Tr(e: Expression, listNeeded: Boolean) : (Boogie.Expr, List[Boogie.Stmt]) = (Tr(e, (ee,et) => et.Tr(ee,listNeeded), listNeeded))
+ def Tr(e: Expression, trrec: (Expression, ExpressionTranslator) => (Boogie.Expr, List[Boogie.Stmt]), listNeeded: Boolean = false): (Boogie.Expr, List[Boogie.Stmt]) = {
+ def trrecursive(e: Expression): (Boogie.Expr, List[Boogie.Stmt]) = trrec(e, this)
desugar(e) match {
- case IntLiteral(n) => n
- case BoolLiteral(b) => b
- case NullLiteral() => bnull
+ case IntLiteral(n) => (n,Nil)
+ case BoolLiteral(b) => (b,Nil)
+ case NullLiteral() => (bnull,Nil)
case StringLiteral(s) =>
// since there currently are no operations defined on string, except == and !=, just translate
// each string to a unique number
- s.hashCode()
- case BoogieExpr(b) => b
+ (s.hashCode(),Nil)
+ case BoogieExpr(b) => (b,Nil)
case MaxLockLiteral() => throw new InternalErrorException("waitlevel case should be handled in << and == and !=")
- case LockBottomLiteral() => bLockBottom
- case _:ThisExpr => VarExpr("this")
- case _:Result => VarExpr("result")
- case ve : VariableExpr => VarExpr(ve.v.UniqueName)
+ case LockBottomLiteral() => (bLockBottom,Nil)
+ case _:ThisExpr => (VarExpr("this"),Nil)
+ case _:Result => (VarExpr("result"),Nil)
+ case ve : VariableExpr => (VarExpr(ve.v.UniqueName),Nil)
case fs @ MemberAccess(e,_) =>
assert(! fs.isPredicate);
- var r = Heap.select(trrecursive(e), fs.f.FullName);
+ var (ee,ll) = trrecursive(e)
+ var r = Heap.select(ee, fs.f.FullName);
if (fs.f.isInstanceOf[SpecialField] && fs.f.id == "joinable")
- r !=@ 0 // joinable is encoded as an integer
+ (r !=@ 0,ll) // joinable is encoded as an integer
else
- r
+ (r,ll)
case _:Permission => throw new InternalErrorException("permission unexpected here")
case _:PermissionExpr => throw new InternalErrorException("permission expression unexpected here: " + e.pos)
case _:Credit => throw new InternalErrorException("credit expression unexpected here")
case Holds(e) =>
- var ee = trrecursive(e)
- (0 < Heap.select(ee, "held")) &&
- !Heap.select(ee, "rdheld")
+ var (ee,ll) = trrecursive(e)
+ ((0 < Heap.select(ee, "held")) &&
+ !Heap.select(ee, "rdheld"),ll)
case RdHolds(e) =>
- Heap.select(trrecursive(e), "rdheld")
+ var (ee,ll) = trrecursive(e)
+ (Heap.select(ee, "rdheld"),ll)
case a: Assigned =>
- VarExpr("assigned$" + a.v.UniqueName)
+ (VarExpr("assigned$" + a.v.UniqueName),Nil)
case Old(e) =>
trrec(e, oldEtran)
case IfThenElse(con, then, els) =>
- Boogie.Ite(trrecursive(con), trrecursive(then), trrecursive(els)) // of type: VarExpr(TrClass(then.typ))
+ var (conE,conL) = trrecursive(con)
+ var (thenE,thenL) = trrecursive(then)
+ var (elsE,elsL) = trrecursive(els)
+ (Boogie.Ite(conE, thenE, elsE), (if (listNeeded) (conL ::: thenL ::: elsL) else Nil)) // of type: VarExpr(TrClass(then.typ))
case Not(e) =>
- ! trrecursive(e)
- case func@FunctionApplication(obj, id, args) =>
- FunctionApp(functionName(func.f), Heap :: (obj :: args map { arg => trrecursive(arg)}))
- case uf@Unfolding(_, e) =>
- trrecursive(e)
+ var (ee,ll) = trrecursive(e)
+ ((! ee),ll)
+ case func@FunctionApplication(obj, id, args) => {
+ var fullArgs = if (!func.f.isStatic) (obj :: args) else (args)
+ var trArgs = fullArgs map {arg => trrecursive(arg)} // yields a list of (Expr, List[Boogie.Stmt]) pairs
+ var trArgsE = trArgs.foldRight(List[Boogie.Expr]())((el, ll) => el._1 :: ll) // collect list of exprs
+ var trArgsL = if (listNeeded) (trArgs.foldRight(List[Boogie.Stmt]())((x,y) => ((x._2) ::: y))) else Nil // concatenate lists of statements
+ (FunctionApp(functionName(func.f), Heap :: trArgsE),trArgsL)
+ }
+ case uf@Unfolding(acc@Access(pred@MemberAccess(obj, f), perm), ufexpr) =>
+ // record extra information resulting from "peeking inside" the predicate, generating appropriate statements (this is used in Exhale of an expression)
+ val (ee,ll) = trrecursive(ufexpr)
+ val (receiverV, receiver) = Boogie.NewBVar("predRec", tref, true)
+ val (versionV, version) = Boogie.NewBVar("predVer", tint, true)
+ val (flagV, flag) = Boogie.NewBVar("predFlag", tbool, true)
+ val o = TrExpr(obj);
+
+ val stmts = if (listNeeded) (BLocal(receiverV) :: (receiver := o) ::
+ BLocal(flagV) :: (flag := true) ::
+ functionTrigger(o, pred.predicate) ::
+ BLocal(versionV) :: (version := Heap.select(o, pred.predicate.FullName)) :::
+ // UpdateSecMaskDuringUnfold(pred.predicate, o, Heap.select(o, pred.predicate.FullName), perm, currentK) :::
+ TransferPermissionToSecMask(pred.predicate, BoogieExpr(receiver), perm, uf.pos, receiver, pred.predicate.FullName, version)) else Nil
+
+ (ee, ll ::: stmts)
case Iff(e0,e1) =>
- trrecursive(e0) <==> trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ ((ee0 <==> ee1), if (listNeeded) (l0 ::: l1) else Nil)
case Implies(e0,e1) =>
- trrecursive(e0) ==> trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ ((ee0 ==> ee1), if (listNeeded) (l0 ::: l1) else Nil)
case And(e0,e1) =>
- trrecursive(e0) && trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ ((ee0 && ee1), if (listNeeded) (l0 ::: l1) else Nil)
case Or(e0,e1) =>
- trrecursive(e0) || trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ ((ee0 || ee1), if (listNeeded) (l0 ::: l1) else Nil)
case Eq(e0,e1) =>
(ShaveOffOld(e0), ShaveOffOld(e1)) match {
case ((MaxLockLiteral(),o0), (MaxLockLiteral(),o1)) =>
if (o0 == o1)
- true
+ (true, Nil) // in this case, l0 and l1 would be Nil, (and Tr((MaxLockLiteral(),_)) is not defined)
else
- MaxLockPreserved
- case ((MaxLockLiteral(),o), _) => ChooseEtran(o).IsHighestLock(trrecursive(e1))
- case (_, (MaxLockLiteral(),o)) => ChooseEtran(o).IsHighestLock(trrecursive(e0))
- case _ => if(e0.typ.IsSeq) FunctionApp("Seq#Equal", List(trrecursive(e0), trrecursive(e1))) else (trrecursive(e0) ==@ trrecursive(e1))
+ (MaxLockPreserved, Nil) // in this case, l0 and l1 would be Nil, (and Tr((MaxLockLiteral(),_)) is not defined)
+ case ((MaxLockLiteral(),o), _) =>
+ var (ee1,l1) = trrecursive(e1)
+ (ChooseEtran(o).IsHighestLock(ee1), l1) // in this case, l0 would be Nil, (and Tr((MaxLockLiteral(),_)) is not defined)
+ case (_, (MaxLockLiteral(),o)) =>
+ var (ee0,l0) = trrecursive(e0)
+ (ChooseEtran(o).IsHighestLock(ee0), l0) // in this case, l1 would be Nil, (and Tr((MaxLockLiteral(),_)) is not defined)
+ case _ =>
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ ((if(e0.typ.IsSeq) FunctionApp("Seq#Equal", List(ee0, ee1)) else (ee0 ==@ ee1)), if (listNeeded) (l0 ::: l1) else Nil)
}
case Neq(e0,e1) =>
trrecursive(Not(Eq(e0,e1)))
case Less(e0,e1) =>
- trrecursive(e0) < trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ (ee0 < ee1, if (listNeeded) (l0 ::: l1) else Nil)
case AtMost(e0,e1) =>
- trrecursive(e0) <= trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ (ee0 <= ee1, if (listNeeded) (l0 ::: l1) else Nil)
case AtLeast(e0,e1) =>
- trrecursive(e0) >= trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ (ee0 >= ee1, if (listNeeded) (l0 ::: l1) else Nil)
case Greater(e0,e1) =>
- trrecursive(e0) > trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ (ee0 > ee1, if (listNeeded) (l0 ::: l1) else Nil)
case LockBelow(e0,e1) => {
- def MuValue(b: Expression): Boogie.Expr =
- if (b.typ.IsRef) new Boogie.MapSelect(Heap, trrecursive(b), "mu") else trrecursive(b)
+ def MuValue(b: Expression): (Boogie.Expr, List[Boogie.Stmt]) = (
+ trrecursive(b) match {
+ case (eb, lb) =>
+ ((if (b.typ.IsRef) new Boogie.MapSelect(Heap, eb, "mu") else eb),lb)
+ }
+ )
(ShaveOffOld(e0), ShaveOffOld(e1)) match {
case ((MaxLockLiteral(),o0), (MaxLockLiteral(),o1)) =>
if (o0 == o1)
- false
+ (false,Nil) // in this case, l0 and l1 are guaranteed to be Nil
else
- TemporalMaxLockComparison(ChooseEtran(o0), ChooseEtran(o1))
- case ((MaxLockLiteral(),o), _) => ChooseEtran(o).MaxLockIsBelowX(MuValue(e1))
- case (_, (MaxLockLiteral(),o)) => ChooseEtran(o).MaxLockIsAboveX(MuValue(e0))
- case _ => new FunctionApp("MuBelow", MuValue(e0), MuValue(e1)) }
+ (TemporalMaxLockComparison(ChooseEtran(o0), ChooseEtran(o1)),Nil) // in this case, l0 and l1 are guaranteed to be Nil
+ case ((MaxLockLiteral(),o), _) =>
+ var (ee1, l1) = MuValue(e1)
+ (ChooseEtran(o).MaxLockIsBelowX(ee1),l1)
+ case (_, (MaxLockLiteral(),o)) =>
+ var (ee0, l0) = MuValue(e0)
+ (ChooseEtran(o).MaxLockIsAboveX(ee0),l0)
+ case _ =>
+ var (ee0, l0) = MuValue(e0)
+ var (ee1, l1) = MuValue(e1)
+ ((new FunctionApp("MuBelow", ee0, ee1)), if (listNeeded) (l0 ::: l1) else Nil) }
}
case Plus(e0,e1) =>
- trrecursive(e0) + trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ (ee0 + ee1, if (listNeeded) (l0 ::: l1) else Nil)
case Minus(e0,e1) =>
- trrecursive(e0) - trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ (ee0 - ee1, if (listNeeded) (l0 ::: l1) else Nil)
case Times(e0,e1) =>
- trrecursive(e0) * trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ (ee0 * ee1, if (listNeeded) (l0 ::: l1) else Nil)
case Div(e0,e1) =>
- trrecursive(e0) / trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ (ee0 / ee1, if (listNeeded) (l0 ::: l1) else Nil)
case Mod(e0,e1) =>
- trrecursive(e0) % trrecursive(e1)
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ (ee0 % ee1, if (listNeeded) (l0 ::: l1) else Nil)
case EmptySeq(t) =>
- createEmptySeq
+ (createEmptySeq, Nil)
case ExplicitSeq(es) =>
es match {
- case Nil => createEmptySeq
- case h :: Nil => createSingletonSeq(trrecursive(h))
- case h :: t => createAppendSeq(createSingletonSeq(trrecursive(h)), trrecursive(ExplicitSeq(t)))
+ case Nil => (createEmptySeq, Nil)
+ case h :: Nil =>
+ var (eh,lh) = trrecursive(h)
+ (createSingletonSeq(eh),lh)
+ case h :: t =>
+ var (eh,lh) = trrecursive(h)
+ var (et,lt) = trrecursive(ExplicitSeq(t))
+ ((createAppendSeq(createSingletonSeq(eh), et)), if (listNeeded) (lh ::: lt) else Nil)
}
case Range(min, max) =>
- createRange(trrecursive(min), trrecursive(max))
+ var (emin,lmin) = trrecursive(min)
+ var (emax,lmax) = trrecursive(max)
+ ((createRange(emin, emax)), if (listNeeded) (lmin ::: lmax) else Nil)
case Append(e0, e1) =>
- createAppendSeq(trrecursive(e0), trrecursive(e1))
- case at@At(e0, e1) =>SeqIndex(trrecursive(e0), trrecursive(e1))
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ ((createAppendSeq(ee0, ee1)), if (listNeeded) (l0 ::: l1) else Nil)
+ case at@At(e0, e1) =>
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ ((SeqIndex(ee0, ee1)), if (listNeeded) (l0 ::: l1) else Nil)
case Drop(e0, e1) =>
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
e1 match {
case IntLiteral(0) =>
- trrecursive(e0)
+ (ee0, if (listNeeded) (l0 ::: l1) else Nil)
case _ =>
- Boogie.FunctionApp("Seq#Drop", List(trrecursive(e0), trrecursive(e1)))
+ ((Boogie.FunctionApp("Seq#Drop", List(ee0, ee1))), if (listNeeded) (l0 ::: l1) else Nil)
}
case Take(e0, e1) =>
- Boogie.FunctionApp("Seq#Take", List(trrecursive(e0), trrecursive(e1)))
- case Length(e) => SeqLength(trrecursive(e))
- case Contains(e0, e1) => SeqContains(trrecursive(e1), trrecursive(e0))
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ ((Boogie.FunctionApp("Seq#Take", List(ee0, ee1))), if (listNeeded) (l0 ::: l1) else Nil)
+ case Length(e) =>
+ var (ee,l) = trrecursive(e)
+ (SeqLength(ee), l)
+ case Contains(e0, e1) =>
+ var (ee0,l0) = trrecursive(e0)
+ var (ee1,l1) = trrecursive(e1)
+ (SeqContains(ee1, ee0), if (listNeeded) (l0 ::: l1) else Nil) // Note: swapping of arguments
case Eval(h, e) =>
val (evalHeap, evalMask, evalSecMask, evalCredits, checks, assumptions) = fromEvalState(h);
val evalEtran = new ExpressionTranslator(Globals(evalHeap, evalMask, evalSecMask, evalCredits), oldEtran.globals, currentClass);
trrec(e, evalEtran)
case _:SeqQuantification => throw new InternalErrorException("should be desugared")
case tq @ TypeQuantification(Forall, _, _, e, _) =>
- Boogie.Forall(Nil, tq.variables map { v => Variable2BVar(v)}, Nil, trrecursive(e))
+ val(ee,l) = trrecursive(e)
+ val groupedTriggerSets = generateTriggers(tq.variables,e)
+ val oneQuantifier : (((List[Trigger],List[Variable])) => Boogie.Expr) = ((trigsAndExtraVars) => (Boogie.Forall(Nil, (tq.variables ::: trigsAndExtraVars._2) map { v => Variable2BVar(v)}, trigsAndExtraVars._1, ee)))
+ var firstTriggerSet : (List[Trigger],List[Variable]) = (Nil,Nil);
+ var restTriggerSet : List[(List[Trigger],List[Variable])] = Nil;
+
+ groupedTriggerSets match {
+ case Nil =>
+ firstTriggerSet = (Nil,Nil); // we will generate no triggers for this quantifier
+ restTriggerSet = Nil
+ case ts :: rest =>
+ firstTriggerSet = ts;
+ restTriggerSet = rest
+ }
+ (restTriggerSet.foldRight(oneQuantifier(firstTriggerSet))((trigset,expr) => (oneQuantifier(trigset) && expr)),l)
case tq @ TypeQuantification(Exists, _, _, e, _) =>
- Boogie.Exists(Nil, tq.variables map { v => Variable2BVar(v)}, Nil, trrecursive(e))
+ var (ee,l) = trrecursive(e)
+ ((Boogie.Exists(Nil, tq.variables map { v => Variable2BVar(v)}, Nil, ee)),l)
}
}
+ // This is used for searching for triggers for quantifiers around the expression "toSearch". The list "vs" gives the variables which need triggering
+ // Returns a list of function applications (the framing function) paired with two sets of variables.
+ // The first set of variables shows which of the "vs" occur (useful for deciding how to select applications for trigger sets later)
+ // The second set of variables indicated the extra boolean variables which were introduced to "hide" problematic logical/comparison operators which may not occur in triggers.
+ // e.g., if vs = [x] and toSearch = f(x, y ==> z) then a singleton list will be returned, containing (f(x,b),{x},{b}).
+ def getFunctionAppsContaining(vs:List[Variable], toSearch : Expression): (List[(Boogie.FunctionApp,Set[Variable],Set[Variable])]) = {
+ var functions: List[(Boogie.FunctionApp,Set[Variable],Set[Variable])] = List() // accumulate candidate functions to return
+ var nestedBoundVars : List[Variable] = List(); // count all variables bound in nested quantifiers, to avoid considering function applications mentioning these
+
+ // get all nested bound vars
+ toSearch visit {
+ _ match {
+ case qe : Quantification =>
+ nestedBoundVars :::= qe.variables
+ case _ =>
+ }
+ }
+
+ // get all function applications
+ toSearch visit {
+ _ match {
+ case fapp@FunctionApplication(obj, id, args) =>
+ var extraVars : Set[Variable] = Set() // collect extra variables generated for this term
+ var containsNestedBoundVars = false // flag to rule out this term
+ // closure to generate fresh boolean variable
+ val freshBoolVar : (() => Option[Expression]) = {() =>
+ val newV = new Variable("b", new Type(BoolClass))
+ extraVars += newV;
+ Some(new VariableExpr(newV))
+ }
+ // replaces problematic logical/comparison expressions with fresh boolean variables
+ val boolExprEliminator : (Expression => Option[Expression]) = ((expr:Expression) =>
+ expr match {
+ case exp@Not(e) => freshBoolVar()
+ case exp@Iff(e0,e1) => freshBoolVar()
+ case exp@Implies(e0,e1) => freshBoolVar()
+ case exp@And(e0,e1) => freshBoolVar()
+ case exp@Or(e0,e1) => freshBoolVar()
+ case Eq(e0,e1) => freshBoolVar()
+ case Neq(e0,e1) => freshBoolVar()
+ case Less(e0,e1) => freshBoolVar()
+ case AtMost(e0,e1) => freshBoolVar()
+ case AtLeast(e0,e1) => freshBoolVar()
+ case Greater(e0,e1) => freshBoolVar()
+ case _ => None
+ });
+ var containedVars : Set[Variable] = Set()
+ val processedArgs = args map (_.transform(boolExprEliminator)) // eliminate all boolean expressions forbidden from triggers, and replace with "extraVars"
+ // collect all the sought (vs) variables in the function application
+ processedArgs map {e => e visit {_ match {
+ case ve@VariableExpr(s) =>
+ val v : Variable = ve.v
+ if (nestedBoundVars.contains(v)) (containsNestedBoundVars = true);
+ if (vs.contains(v)) (containedVars += v)
+ case _ =>}
+ }
+ }
+ if (!containsNestedBoundVars && !containedVars.isEmpty) {
+ val fullArgs = if (!fapp.f.isStatic) (obj :: processedArgs) else (processedArgs)
+ val noOldETran = this.UseCurrentAsOld();
+ val trArgs = fullArgs map {arg => noOldETran.Tr(arg)} // translate args
+ val triggerFunctionName = functionName(fapp.f) + "#limited#trigger";
+ functions ::= (FunctionApp(triggerFunctionName, trArgs),containedVars,extraVars)
+ }
+ case _ =>}
+ }
+ functions
+ }
+
+
+
+
+ // Precondition : if vars is non-empty then every (f,vs) pair in functs satisfies the property that vars and vs are not disjoint.
+ // Finds trigger sets by selecting entries from "functs" until all of "vars" occur, and accumulating the extra variables needed for each function term.
+ // Returns a list of the trigger sets found, paired with the extra boolean variables they use
+def buildTriggersCovering(vars : Set[Variable], functs : List[(Boogie.FunctionApp,Set[Variable],Set[Variable])], currentTrigger : List[Expr], extraVars : Set[Variable]) : List[(Trigger,Set[Variable])] = {
+ if (vars.isEmpty) (List((Boogie.Trigger(currentTrigger),extraVars))) // we have found a suitable trigger set
+ else (functs match {
+ case Nil => Nil // this branch didn't result in a solution
+ case ((f,vs,extra) :: rest) => {
+ val needed : Set[Variable] = vars.diff(vs) // variables still not triggered
+ // try adding the next element of functs, or not..
+ buildTriggersCovering(needed, (rest.filter(func => !func._2.intersect(needed).isEmpty)), f :: currentTrigger, extraVars|extra) ::: buildTriggersCovering(vars, rest, currentTrigger, extraVars)
+ }
+ }
+ )
+ }
+
+
+ // Generates trigger sets to cover the variables "vs", by searching the expression "toSearch".
+ // Returns a list of pairs of lists of trigger sets couple with the extra variables they require to be quantified over (each list of triggers must contain trigger sets which employ exactly the same extra variables).
+ def generateTriggers(vs: List[Variable], toSearch : Expression) : List[(List[Trigger],List[Variable])] = {
+ val functionApps : (List[(Boogie.FunctionApp,Set[Variable],Set[Variable])]) = getFunctionAppsContaining(vs, toSearch) // find suitable function applications
+ if (functionApps.isEmpty) List() else {
+ var triggerSetsToUse : List[(Trigger,Set[Variable])] = buildTriggersCovering(Set() ++ vs, functionApps, Nil, Set())
+ var groupedTriggerSets : List[(List[Trigger],List[Variable])] = List() // group trigger sets by those which use the same sets of extra boolean variables
+
+ while (!triggerSetsToUse.isEmpty) {
+ triggerSetsToUse.partition((ts : (Trigger,Set[Variable])) => triggerSetsToUse.head._2.equals(ts._2)) match {
+ case (sameVars,rest) =>
+ triggerSetsToUse = rest;
+ groupedTriggerSets ::= ((sameVars map (_._1)), sameVars.head._2.toList)
+ }
+ }
+ groupedTriggerSets
+ }
+ }
+
+
/** translate everything, including permissions and credit expressions */
+ // Since this is only used in axiom generation (so far), the ability to generate "side-effects" from the evaluation of unfolding expressions (as in the list of boogie statements returned from Tr) is not implemented here (in axioms the side-effects are not wanted anyway)
def TrAll(e: Expression): Expr = {
def TrAllHelper(e: Expression, etran: ExpressionTranslator): Expr = e match {
case pred@MemberAccess(e, p) if pred.isPredicate =>
@@ -1876,7 +2198,7 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
val memberName = member.f.FullName;
val (refV, ref) = Boogie.NewBVar("ref", tref, true);
(SeqContains(Tr(s), ref) ==> CanRead(ref, memberName)).forall(refV)
- case _ => etran.Tr(e, TrAllHelper)
+ case _ => (etran.Tr(e, (ee : Expression, et : ExpressionTranslator) => (TrAllHelper(ee,et),Nil)))._1 //wrap TrAllHelper to give it the return type needed for Tr.
}
TrAllHelper(e, this)
}
@@ -1896,14 +2218,14 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
***************** INHALE/EXHALE *****************
**********************************************************************/
- def Inhale(predicates: List[Expression], occasion: String, check: Boolean, currentK: Expr): List[Boogie.Stmt] = {
+ def Inhale(predicates: List[Expression], occasion: String, check: Boolean, currentK: Expr, unfoldReceiver: VarExpr = null, unfoldPredicateName: String = null, unfoldVersion: VarExpr = null): List[Boogie.Stmt] = {
if (predicates.size == 0) return Nil;
//val (ihV, ih) = Boogie.NewBVar("inhaleHeap", theap, true)
Comment("inhale (" + occasion + ")") ::
//BLocal(ihV) :: Boogie.Havoc(ih) ::
//bassume(IsGoodInhaleState(ih, Heap, Mask, SecMask)) ::
- (for (p <- predicates) yield Inhale(p, Heap, check, currentK)).flatten :::
+ (for (p <- predicates) yield Inhale(p, Heap, check, currentK, unfoldReceiver, unfoldPredicateName, unfoldVersion)).flatten :::
bassume(AreGoodMasks(Mask, SecMask)) ::
bassume(wf(Heap, Mask, SecMask)) ::
Comment("end inhale")
@@ -1917,25 +2239,25 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
stmts :::
(perm.permissionType match {
case PermissionType.Mixed =>
- bassume(f > 0 || (f == 0 && n > 0)) ::
+ bassume(f > 0.0 || (f == 0.0 && n > 0.0)) ::
IncPermission(obj, memberName, f, m) :::
IncPermissionEpsilon(obj, memberName, n, m)
case PermissionType.Epsilons =>
- bassume(n > 0) ::
+ bassume(n > 0.0) ::
IncPermissionEpsilon(obj, memberName, n, m)
case PermissionType.Fraction =>
- bassume(f > 0) ::
+ bassume(f > 0.0) ::
IncPermission(obj, memberName, f, m)
})
}
- def Inhale(p: Expression, ih: Boogie.Expr, check: Boolean, currentK: Expr): List[Boogie.Stmt] =
- InhaleImplementation(p, ih, check, currentK, false)
+ def Inhale(p: Expression, ih: Boogie.Expr, check: Boolean, currentK: Expr, unfoldReceiver: VarExpr, unfoldPredicateName : String, unfoldVersion: VarExpr): List[Boogie.Stmt] =
+ InhaleImplementation(p, ih, check, currentK, false, unfoldReceiver, unfoldPredicateName, unfoldVersion)
- def InhaleToSecMask(p: Expression): List[Boogie.Stmt] =
- InhaleImplementation(p, Heap /* it should not matter what we pass here */, false /* check */, -1 /* it should not matter what we pass here */, true)
+ def InhaleToSecMask(p: Expression, unfoldingReceiver: VarExpr = null, unfoldingPredicateName: String = null, unfoldingVersion: VarExpr = null): List[Boogie.Stmt] =
+ InhaleImplementation(p, Heap /* it should not matter what we pass here */, false /* check */, -1 /* it should not matter what we pass here */, true, unfoldingReceiver, unfoldingPredicateName, unfoldingVersion)
- def InhaleImplementation(p: Expression, ih: Boogie.Expr, check: Boolean, currentK: Expr, transferToSecMask: Boolean): List[Boogie.Stmt] = desugar(p) match {
+ def InhaleImplementation(p: Expression, ih: Boogie.Expr, check: Boolean, currentK: Expr, transferToSecMask: Boolean, unfoldReceiver: VarExpr = null, unfoldPredicateName: String = null, unfoldVersion: VarExpr = null): List[Boogie.Stmt] = desugar(p) match {
case pred@MemberAccess(e, p) if pred.isPredicate =>
val chk = (if (check) {
isDefined(e)(true) :::
@@ -1943,7 +2265,7 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
} else Nil)
val tmp = Access(pred, Full);
tmp.pos = pred.pos;
- chk ::: InhaleImplementation(tmp, ih, check, currentK, transferToSecMask)
+ chk ::: InhaleImplementation(tmp, ih, check, currentK, transferToSecMask, unfoldReceiver, unfoldPredicateName, unfoldVersion)
case AccessAll(obj, perm) => throw new InternalErrorException("should be desugared")
case AccessSeq(s, None, perm) => throw new InternalErrorException("should be desugared")
case acc@Access(e,perm) =>
@@ -1958,6 +2280,8 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
bassume(wf(Heap, Mask, SecMask)) ::
(if(e.isPredicate) Nil else List(bassume(TypeInformation(new Boogie.MapSelect(Heap, trE, memberName), e.f.typ.typ)))) :::
InhalePermission(perm, trE, memberName, currentK, (if (transferToSecMask) SecMask else Mask)) :::
+ // record "inside" relationship for predicate instances
+ (if(e.isPredicate && unfoldReceiver != null) bassume(FunctionApp("#predicateInside#", unfoldReceiver :: VarExpr(unfoldPredicateName) :: unfoldVersion :: trE :: VarExpr(memberName) :: Heap.select(trE, memberName) :: Nil)) :: Nil else Nil) :::
bassume(AreGoodMasks(Mask, SecMask)) ::
bassume(wf(Heap, Mask, SecMask)) ::
bassume(wf(ih, Mask, SecMask))
@@ -1975,9 +2299,9 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
// assume that the permission is positive
bassume((SeqContains(e, ref) ==>
(perm.permissionType match {
- case PermissionType.Fraction => r > 0
- case PermissionType.Mixed => r > 0 || (r == 0 && n > 0)
- case PermissionType.Epsilons => n > 0
+ case PermissionType.Fraction => r > 0.0
+ case PermissionType.Mixed => r > 0.0 || (r == 0.0 && n > 0.0)
+ case PermissionType.Epsilons => n > 0.0
})).forall(refV)) ::
(if (check) isDefined(s)(true) ::: isDefined(perm)(true) else Nil) :::
{
@@ -2017,12 +2341,12 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
new Boogie.MapUpdate(Credits, trCh, new Boogie.MapSelect(Credits, trCh) + Tr(cr.N))
case Implies(e0,e1) =>
(if(check) isDefined(e0)(true) else Nil) :::
- Boogie.If(Tr(e0), InhaleImplementation(e1, ih, check, currentK, transferToSecMask), Nil)
+ Boogie.If(Tr(e0), InhaleImplementation(e1, ih, check, currentK, transferToSecMask, unfoldReceiver, unfoldPredicateName, unfoldVersion), Nil)
case IfThenElse(con, then, els) =>
(if(check) isDefined(con)(true) else Nil) :::
- Boogie.If(Tr(con), InhaleImplementation(then, ih, check, currentK, transferToSecMask), InhaleImplementation(els, ih, check, currentK, transferToSecMask))
+ Boogie.If(Tr(con), InhaleImplementation(then, ih, check, currentK, transferToSecMask, unfoldReceiver, unfoldPredicateName, unfoldVersion), InhaleImplementation(els, ih, check, currentK, transferToSecMask, unfoldReceiver, unfoldPredicateName, unfoldVersion))
case And(e0,e1) =>
- InhaleImplementation(e0, ih, check, currentK, transferToSecMask) ::: InhaleImplementation(e1, ih, check, currentK, transferToSecMask)
+ InhaleImplementation(e0, ih, check, currentK, transferToSecMask) ::: InhaleImplementation(e1, ih, check, currentK, transferToSecMask, unfoldReceiver, unfoldPredicateName, unfoldVersion)
case holds@Holds(e) =>
val trE = Tr(e);
(if(check)
@@ -2060,7 +2384,7 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
bassume(AreGoodMasks(preEtran.Mask, preEtran.SecMask)) ::
bassume(wf(preEtran.Heap, preEtran.Mask, preEtran.SecMask)) ::
bassume(proofOrAssume) ::
- preEtran.InhaleImplementation(e, ih, check, currentK, transferToSecMask) :::
+ preEtran.InhaleImplementation(e, ih, check, currentK, transferToSecMask, unfoldReceiver, unfoldPredicateName, unfoldVersion) :::
bassume(preEtran.Heap ==@ evalHeap) ::
bassume(submask(preEtran.Mask, evalMask))
case uf@Unfolding(acc@Access(pred@MemberAccess(obj, f), perm), ufexpr) =>
@@ -2080,7 +2404,7 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
if (isOldEtran) Nil else
// remove secondary permissions (if any), and add them again
UpdateSecMaskDuringUnfold(pred.predicate, o, Heap.select(o, pred.predicate.FullName), perm, currentK) :::
- TransferPermissionToSecMask(pred.predicate, BoogieExpr(receiver), perm, uf.pos)
+ TransferPermissionToSecMask(pred.predicate, BoogieExpr(receiver), perm, uf.pos, receiver, pred.predicate.FullName, version)
) :::
bassume(Tr(uf))
@@ -2096,10 +2420,10 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
/** Transfer the permissions mentioned in the body of the predicate to the
* secondary mask.
*/
- def TransferPermissionToSecMask(pred: Predicate, obj: Expression, perm: Permission, pos: Position): List[Stmt] = {
+ def TransferPermissionToSecMask(pred: Predicate, obj: Expression, perm: Permission, pos: Position, unfoldingReceiver: VarExpr = null, unfoldingPredicateName: String = null, unfoldingVersion: VarExpr = null): List[Stmt] = {
var definition = scaleExpressionByPermission(SubstThis(DefinitionOf(pred), obj), perm, pos)
// go through definition and handle all permisions correctly
- InhaleToSecMask(definition)
+ InhaleToSecMask(definition, unfoldingReceiver, unfoldingPredicateName, unfoldingVersion)
}
// Exhale is done in two passes: In the first run, everything except permissions
@@ -2125,8 +2449,8 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
Exhale(m, sm, predicates, occasion, check, currentK, exactchecking, false, -1, false, null, false)
}
/** Exhale that transfers permission to the secondary mask */
- def ExhaleAndTransferToSecMask(predicates: List[(Expression, ErrorMessage)], occasion: String, currentK: Expr, exactchecking: Boolean): List[Boogie.Stmt] = {
- Exhale(Mask, SecMask, predicates, occasion, false, currentK, exactchecking, true /* transfer to SecMask */, -1, false, null, false)
+ def ExhaleAndTransferToSecMask(receiver: Expr, pred: Predicate, predicates: List[(Expression, ErrorMessage)], occasion: String, currentK: Expr, exactchecking: Boolean, foldReceiver: VarExpr = null, foldPredicateName: String = null, foldVersion: VarExpr = null): List[Boogie.Stmt] = {
+ Exhale(receiver, pred, Mask, SecMask, predicates, occasion, false, currentK, exactchecking, true /* transfer to SecMask */, -1, false, null, false, foldReceiver, foldPredicateName, foldVersion)
}
/** Remove permission from the secondary mask, and assume all assertions that
* would get generated. Recursion is bouded by the parameter depth.
@@ -2138,36 +2462,9 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
def UpdateSecMaskDuringUnfold(predicate: Predicate, receiver: Expr, version: Expr, perm: Permission, currentK: Expr): List[Stmt] = {
UpdateSecMask(predicate, receiver, version, perm, currentK, 1, Map())
}
+ // no longer relevant (as of Sept 2012), since we don't take this approach with secondary mask any more
def UpdateSecMask(predicate: Predicate, receiver: Expr, version: Expr, perm: Permission, currentK: Expr, depth: Int, previousReceivers: Map[String,List[Expr]]): List[Stmt] = {
- assert (depth >= 0)
- if (depth <= 0) return Nil
-
- val definition = scaleExpressionByPermission(SubstThis(DefinitionOf(predicate), BoogieExpr(receiver)), perm, NoPosition)
- val occasion = "update SecMask"
-
- // condition: if any folded predicate matches (both receiver and version), update the secondary map
- val disj = (for (fp <- etran.fpi.getFoldedPredicates(predicate)) yield {
- val conditions = (fp.conditions map (c => if (c._2) c._1 else !c._1)).foldLeft(true: Expr){ (a: Expr, b: Expr) => a && b }
- val b = fp.version ==@ version && fp.receiver ==@ receiver && conditions && fp.flag
- (b, fp.flag)
- })
- val b = (disj map (a => a._1)).foldLeft(false: Expr){ (a: Expr, b: Expr) => a || b }
-
- // add receiver to list of previous receivers
- val newPreviousReceivers = previousReceivers + (predicate.FullName -> (receiver :: previousReceivers.getOrElse(predicate.FullName, Nil)))
-
- // assumption that the current receiver is different from all previous ones
- (for (r <- previousReceivers.getOrElse(predicate.FullName, Nil)) yield {
- bassume(receiver !=@ r)
- }) :::
- // actually update the secondary mask
- Boogie.If(b,
- // remove correct predicate from the auxiliary information by setting
- // its flag to false
- (disj.foldLeft(Nil: List[Stmt]){ (a: List[Stmt], b: (Expr, Expr)) => Boogie.If(b._1,/*(b._2 := false) :: */Nil,a) :: Nil }) :::
- // asserts are converted to assumes, so error messages do not matter
- assert2assume(Exhale(SecMask, SecMask, List((definition, ErrorMessage(NoPosition, ""))), occasion, false, currentK, false /* it should not important what we pass here */, false, depth-1, true, newPreviousReceivers, false)),
- Nil) :: Nil
+ Nil
}
/** Most general form of exhale; implements all the specific versions above */
// Note: If isUpdatingSecMask, then m is actually a secondary mask, and at the
@@ -2190,27 +2487,33 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
// previousReceivers is not needed, and thus null.
// Assumption 4+5: duringUnfold can only be true if transferPermissionToSecMask
// and isUpdatingSecMask are not.
- def Exhale(m: Expr, sm: Expr, predicates: List[(Expression, ErrorMessage)], occasion: String, check: Boolean, currentK: Expr, exactchecking: Boolean, transferPermissionToSecMask: Boolean, recurseOnPredicatesDepth: Int, isUpdatingSecMask: Boolean, previousReceivers: Map[String,List[Expr]], duringUnfold: Boolean): List[Boogie.Stmt] = {
+ // Assumption 6: foldReceiver, foldPredicateName, foldVersion are all either non-null (in which case this exhale is the body of the corresponding predicate instance being folded) or all non-null.
+ def Exhale(m: Expr, sm: Expr, predicates: List[(Expression, ErrorMessage)], occasion: String, check: Boolean, currentK: Expr, exactchecking: Boolean, transferPermissionToSecMask: Boolean, recurseOnPredicatesDepth: Int, isUpdatingSecMask: Boolean, previousReceivers: Map[String,List[Expr]], duringUnfold: Boolean, foldReceiver: VarExpr = null, foldPredicateName: String = null, foldVersion: VarExpr = null): List[Boogie.Stmt] =
+ Exhale(null, null, m, sm, predicates, occasion, check, currentK, exactchecking, transferPermissionToSecMask, recurseOnPredicatesDepth, isUpdatingSecMask, previousReceivers, duringUnfold, foldReceiver, foldPredicateName, foldVersion)
+ def Exhale(receiver: Expr, pred: Predicate, m: Expr, sm: Expr, predicates: List[(Expression, ErrorMessage)], occasion: String, check: Boolean, currentK: Expr, exactchecking: Boolean, transferPermissionToSecMask: Boolean, recurseOnPredicatesDepth: Int, isUpdatingSecMask: Boolean, previousReceivers: Map[String,List[Expr]], duringUnfold: Boolean, foldReceiver: VarExpr, foldPredicateName: String, foldVersion: VarExpr): List[Boogie.Stmt] = {
assert ((isUpdatingSecMask && recurseOnPredicatesDepth >= 0) || (!isUpdatingSecMask && recurseOnPredicatesDepth == -1)) // check assumption 2
assert (isUpdatingSecMask || (previousReceivers == null))
assert (!(isUpdatingSecMask && duringUnfold))
assert (!(transferPermissionToSecMask && duringUnfold))
+ assert ((foldReceiver == null) == (foldPredicateName == null))
+ assert ((foldPredicateName == null) == (foldVersion == null))
if (predicates.size == 0) return Nil;
val (ehV, eh) = Boogie.NewBVar("exhaleHeap", theap, true)
var (emV, em: Expr) = Boogie.NewBVar("exhaleMask", tmask, true)
Comment("begin exhale (" + occasion + ")") ::
- (if (!isUpdatingSecMask && !duringUnfold)
+ (if (!isUpdatingSecMask && !duringUnfold && !transferPermissionToSecMask)
BLocal(emV) :: (em := m) ::
BLocal(ehV) :: Boogie.Havoc(eh) :: Nil
else {
em = m
Nil
}) :::
- (for (p <- predicates) yield ExhaleHelper(p._1, em, sm, eh, p._2, check, currentK, exactchecking, false, transferPermissionToSecMask, recurseOnPredicatesDepth, isUpdatingSecMask, previousReceivers, duringUnfold)).flatten :::
- (for (p <- predicates) yield ExhaleHelper(p._1, em, sm, eh, p._2, check, currentK, exactchecking, true, transferPermissionToSecMask, recurseOnPredicatesDepth, isUpdatingSecMask, previousReceivers, duringUnfold)).flatten :::
- (if (!isUpdatingSecMask && !duringUnfold)
+ (for (p <- predicates) yield ExhaleHelper(p._1, em, sm, eh, p._2, check, currentK, exactchecking, false, transferPermissionToSecMask, recurseOnPredicatesDepth, isUpdatingSecMask, previousReceivers, duringUnfold, foldReceiver, foldPredicateName, foldVersion )).flatten :::
+ (for (p <- predicates) yield ExhaleHelper(p._1, em, sm, eh, p._2, check, currentK, exactchecking, true, transferPermissionToSecMask, recurseOnPredicatesDepth, isUpdatingSecMask, previousReceivers, duringUnfold, foldReceiver, foldPredicateName, foldVersion )).flatten :::
+ (if (!isUpdatingSecMask && !duringUnfold && !transferPermissionToSecMask)
(m := em) ::
bassume(IsGoodExhaleState(eh, Heap, m, sm)) ::
+ //restoreFoldedLocations(m, Heap, eh) :::
(Heap := eh) :: Nil
else Nil) :::
(if (isUpdatingSecMask) Nil else bassume(AreGoodMasks(m, sm)) :: Nil) :::
@@ -2218,6 +2521,60 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
Comment("end exhale")
}
+ /** copy all the values of locations that are folded under any predicate (that we care about) one or more levels down from 'heap' to 'exhaleHeap' */
+ def restoreFoldedLocations(mask: Expr, heap: Boogie.Expr, exhaleHeap: Boogie.Expr): List[Boogie.Stmt] = {
+ val foldedPredicates = etran.fpi.getFoldedPredicates()
+ (for (fp <- foldedPredicates) yield {
+ val stmts = bassume(IsGoodExhalePredicateState(exhaleHeap, heap, heap.select(fp.receiver, fp.predicate.FullName+"#m")))
+ Boogie.If(CanRead(fp.receiver, fp.predicate.FullName, mask, ZeroMask) && heap.select(fp.receiver, fp.predicate.FullName) ==@ fp.version, stmts, Nil) :: Nil
+ }) flatten
+ }
+
+ /** the actual recursive method for restoreFoldedLocationsHelperPred */
+ def keepFoldedLocations(expr: Expression, foldReceiver: Expr, foldPred: Predicate, mask: Expr, heap: Boogie.Expr, otherPredicates: List[FoldedPredicate]): List[Boogie.Stmt] = {
+ val f = (expr: Expression) => keepFoldedLocations(expr, foldReceiver, foldPred, mask, heap, otherPredicates)
+ expr match {
+ case pred@MemberAccess(e, p) if pred.isPredicate =>
+ val tmp = Access(pred, Full);
+ tmp.pos = pred.pos;
+ f(tmp)
+ case AccessAll(obj, perm) =>
+ throw new InternalErrorException("not implemented yet")
+ case AccessSeq(s, None, perm) =>
+ throw new InternalErrorException("not implemented yet")
+ case acc@Access(e,perm) =>
+ val memberName = if (e.isPredicate) e.predicate.FullName else e.f.FullName;
+ val trE = Tr(e.e)
+ (if (e.isPredicate) {
+ val (ttV,tt) = Boogie.NewTVar("T")
+ val (refV, ref) = Boogie.NewBVar("ref", tref, true)
+ val (fV, f) = Boogie.NewBVar("f", FieldType(tt), true)
+ val (pmV, pm: Expr) = Boogie.NewBVar("newPredicateMask", tpmask, true)
+ val assumption = (heap.select(foldReceiver, foldPred.FullName+"#m").select(ref, f.id) || heap.select(trE, memberName+"#m").select(ref, f.id)) ==> pm.select(ref, f.id)
+ BLocal(pmV) :: Havoc(pm) ::
+ bassume(new Boogie.Forall(ttV, fV, assumption).forall(refV)) ::
+ (heap.select(foldReceiver, foldPred.FullName+"#m") := pm) :: Nil
+ } else Nil) :::
+ (heap.select(foldReceiver, foldPred.FullName+"#m").select(trE, memberName) := true) :: Nil
+ case acc @ AccessSeq(s, Some(member), perm) =>
+ throw new InternalErrorException("not implemented yet")
+ case cr@Credit(ch, n) =>
+ Nil
+ case Implies(e0,e1) =>
+ Boogie.If(Tr(e0), f(e1), Nil)
+ case IfThenElse(con, then, els) =>
+ Boogie.If(Tr(con), f(then), f(els))
+ case And(e0,e1) =>
+ f(e0) ::: f(e1)
+ case holds@Holds(e) =>
+ Nil
+ case Eval(h, e) =>
+ Nil
+ case e =>
+ Nil
+ }
+ }
+
// see comment in front of method exhale about parameter isUpdatingSecMask
def ExhalePermission(perm: Permission, obj: Expr, memberName: String, currentK: Expr, pos: Position, error: ErrorMessage, em: Boogie.Expr, exactchecking: Boolean, isUpdatingSecMask: Boolean): List[Boogie.Stmt] = {
val (f, stmts) = extractKFromPermission(perm, currentK)
@@ -2226,15 +2583,15 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
val res = stmts :::
(perm.permissionType match {
case PermissionType.Mixed =>
- bassert(f > 0 || (f == 0 && n > 0), error.pos, error.message + " The permission at " + pos + " might not be positive.") ::
+ bassert(f > 0.0 || (f == 0.0 && n > 0.0), error.pos, error.message + " The permission at " + pos + " might not be positive.") ::
(if (isUpdatingSecMask) DecPermissionBoth2(obj, memberName, f, n, em, error, pos, exactchecking)
else DecPermissionBoth(obj, memberName, f, n, em, error, pos, exactchecking))
case PermissionType.Epsilons =>
- bassert(n > 0, error.pos, error.message + " The permission at " + pos + " might not be positive.") ::
+ bassert(n > 0.0, error.pos, error.message + " The permission at " + pos + " might not be positive.") ::
(if (isUpdatingSecMask) DecPermissionEpsilon2(obj, memberName, n, em, error, pos)
else DecPermissionEpsilon(obj, memberName, n, em, error, pos))
case PermissionType.Fraction =>
- bassert(f > 0, error.pos, error.message + " The permission at " + pos + " might not be positive.") ::
+ bassert(f > 0.0, error.pos, error.message + " The permission at " + pos + " might not be positive.") ::
(if (isUpdatingSecMask) DecPermission2(obj, memberName, f, em, error, pos, exactchecking)
else DecPermission(obj, memberName, f, em, error, pos, exactchecking))
})
@@ -2273,46 +2630,34 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
}
}
- def ExhaleHelper(p: Expression, m: Boogie.Expr, sm: Boogie.Expr, eh: Boogie.Expr, error: ErrorMessage, check: Boolean, currentK: Expr, exactchecking: Boolean, onlyExactCheckingPermissions: Boolean, transferPermissionToSecMask: Boolean, recurseOnPredicatesDepth: Int, isUpdatingSecMask: Boolean, previousReceivers: Map[String,List[Expr]], duringUnfold: Boolean): List[Boogie.Stmt] = desugar(p) match {
+ def ExhaleHelper(p: Expression, m: Boogie.Expr, sm: Boogie.Expr, eh: Boogie.Expr, error: ErrorMessage, check: Boolean, currentK: Expr, exactchecking: Boolean, onlyExactCheckingPermissions: Boolean, transferPermissionToSecMask: Boolean, recurseOnPredicatesDepth: Int, isUpdatingSecMask: Boolean, previousReceivers: Map[String,List[Expr]], duringUnfold: Boolean, foldReceiver: VarExpr = null, foldPredicateName: String = null, foldVersion: VarExpr = null): List[Boogie.Stmt] = {
+ val LocalExhaleHelper = (expr: Expression) => ExhaleHelper(expr, m, sm, eh, error, check, currentK, exactchecking, onlyExactCheckingPermissions, transferPermissionToSecMask, recurseOnPredicatesDepth, isUpdatingSecMask, previousReceivers, duringUnfold, foldReceiver, foldPredicateName, foldVersion)
+ desugar(p) match {
case pred@MemberAccess(e, p) if pred.isPredicate =>
val tmp = Access(pred, Full);
tmp.pos = pred.pos;
- ExhaleHelper(tmp, m, sm, eh, error, check, currentK, exactchecking, onlyExactCheckingPermissions, transferPermissionToSecMask, recurseOnPredicatesDepth, isUpdatingSecMask, previousReceivers, duringUnfold)
+ LocalExhaleHelper(tmp)
case AccessAll(obj, perm) => throw new InternalErrorException("should be desugared")
case AccessSeq(s, None, perm) => throw new InternalErrorException("should be desugared")
case acc@Access(e,perm) =>
val ec = needExactChecking(perm, exactchecking)
if (ec != onlyExactCheckingPermissions) Nil else {
val memberName = if(e.isPredicate) e.predicate.FullName else e.f.FullName;
- val (starKV, starK) = NewBVar("starK", tint, true);
+ val (starKV, starK) = NewBVar("starK", treal, true);
val trE = Tr(e.e)
// check definedness
(if(check) isDefined(e.e)(true) :::
bassert(nonNull(Tr(e.e)), error.pos, error.message + " The target of the acc predicate at " + acc.pos + " might be null.") else Nil) :::
+ (if(e.isPredicate && foldReceiver != null) bassume(FunctionApp("#predicateInside#", foldReceiver :: VarExpr(foldPredicateName) :: foldVersion :: trE :: VarExpr(memberName) :: Heap.select(trE, memberName) :: Nil)) :: Nil else Nil) :::
// if the mask does not contain sufficient permissions, try folding acc(e, fraction)
// TODO: include automagic again
// check that the necessary permissions are there and remove them from the mask
ExhalePermission(perm, trE, memberName, currentK, acc.pos, error, m, ec, isUpdatingSecMask) :::
- // transfer permission to secondary mask if necessary
- (if (transferPermissionToSecMask) InhalePermission(perm, trE, memberName, currentK, sm)
- else Nil) :::
- // give up secondary permission to locations of the body of the predicate (also recursively)
- (if (e.isPredicate && !transferPermissionToSecMask)
- (if (isUpdatingSecMask)
- UpdateSecMask(e.predicate, trE, Heap.select(trE, memberName), perm, currentK, recurseOnPredicatesDepth, previousReceivers)
- else
- (if (duringUnfold)
- UpdateSecMaskDuringUnfold(e.predicate, trE, Heap.select(trE, memberName), perm, currentK)
- else
- UpdateSecMask(e.predicate, trE, Heap.select(trE, memberName), perm, currentK)
- )
- )
- else Nil) :::
// update version number (if necessary)
(if (e.isPredicate && !isUpdatingSecMask)
Boogie.If(!CanRead(trE, memberName, m, sm), // if we cannot access the predicate anymore, then its version will be havoced
- (if (!duringUnfold) bassume(Heap.select(trE, memberName) < eh.select(trE, memberName)) :: Nil // assume that the predicate's version grows monotonically
+ (if (!duringUnfold) (if (!transferPermissionToSecMask) bassume(Heap.select(trE, memberName) < eh.select(trE, memberName)) :: Nil else Nil) // assume that the predicate's version grows monotonically
else { // duringUnfold -> the heap is not havoced, thus we need to locally havoc the version
val (oldVersV, oldVers) = Boogie.NewBVar("oldVers", tint, true)
val (newVersV, newVers) = Boogie.NewBVar("newVers", tint, true)
@@ -2322,7 +2667,6 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
}),
Nil) :: Nil
else Nil) :::
- (if (isUpdatingSecMask) Nil else bassume(AreGoodMasks(m, sm)) :: Nil) :::
bassume(wf(Heap, m, sm)) :::
(if (m != Mask || sm != SecMask) bassume(wf(Heap, Mask, SecMask)) :: Nil else Nil)
}
@@ -2349,19 +2693,19 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
// assert that the permission is positive
bassert((SeqContains(e, ref) ==>
(perm.permissionType match {
- case PermissionType.Fraction => r > 0
- case PermissionType.Mixed => r > 0 || (r == 0 && n > 0)
- case PermissionType.Epsilons => n > 0
+ case PermissionType.Fraction => r > 0.0
+ case PermissionType.Mixed => r > 0.0 || (r == 0.0 && n > 0.0)
+ case PermissionType.Epsilons => n > 0.0
})).forall(refV), error.pos, error.message + " The permission at " + acc.pos + " might not be positive.") ::
// make sure enough permission is available
// (see comment in front of method exhale for explanation of isUpdatingSecMask)
(if (!isUpdatingSecMask) bassert((SeqContains(e, ref) ==>
((perm,perm.permissionType) match {
- case _ if !ec => mr > 0
- case (Star,_) => mr > 0
- case (_,PermissionType.Fraction) => r <= mr && (r ==@ mr ==> 0 <= mn)
+ case _ if !ec => mr > 0.0
+ case (Star,_) => mr > 0.0
+ case (_,PermissionType.Fraction) => r <= mr && (r ==@ mr ==> 0.0 <= mn)
case (_,PermissionType.Mixed) => r <= mr && (r ==@ mr ==> n <= mn)
- case (_,PermissionType.Epsilons) => mr ==@ 0 ==> n <= mn
+ case (_,PermissionType.Epsilons) => mr ==@ 0.0 ==> n <= mn
})).forall(refV), error.pos, error.message + " Insufficient permission at " + acc.pos + " for " + member.f.FullName) :: Nil else Nil) :::
// additional assumption on k if we have a star permission or use inexact checking
( perm match {
@@ -2375,7 +2719,6 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
Lambda(List(), List(pcV), (pc ==@ "perm$R").thenElse(mr - r, mn - n)),
m(ref, f))))
} :::
- (if (isUpdatingSecMask) Nil else bassume(AreGoodMasks(m, sm)) :: Nil) :::
bassume(wf(Heap, m, sm)) :::
(if (m != Mask || sm != SecMask) bassume(wf(Heap, Mask, SecMask)) :: Nil else Nil)
}
@@ -2393,12 +2736,12 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
else Nil)
case Implies(e0,e1) =>
(if(check && !onlyExactCheckingPermissions) isDefined(e0)(true) else Nil) :::
- Boogie.If(Tr(e0), ExhaleHelper(e1, m, sm, eh, error, check, currentK, exactchecking, onlyExactCheckingPermissions, transferPermissionToSecMask, recurseOnPredicatesDepth, isUpdatingSecMask, previousReceivers, duringUnfold), Nil)
+ Boogie.If(Tr(e0), LocalExhaleHelper(e1), Nil)
case IfThenElse(con, then, els) =>
(if(check) isDefined(con)(true) else Nil) :::
- Boogie.If(Tr(con), ExhaleHelper(then, m, sm, eh, error, check, currentK, exactchecking, onlyExactCheckingPermissions, transferPermissionToSecMask, recurseOnPredicatesDepth, isUpdatingSecMask, previousReceivers, duringUnfold), ExhaleHelper(els, m, sm, eh, error, check, currentK, exactchecking, onlyExactCheckingPermissions, transferPermissionToSecMask, recurseOnPredicatesDepth, isUpdatingSecMask, previousReceivers, duringUnfold))
+ Boogie.If(Tr(con), LocalExhaleHelper(then), LocalExhaleHelper(els))
case And(e0,e1) =>
- ExhaleHelper(e0, m, sm, eh, error, check, currentK, exactchecking, onlyExactCheckingPermissions, transferPermissionToSecMask, recurseOnPredicatesDepth, isUpdatingSecMask, previousReceivers, duringUnfold) ::: ExhaleHelper(e1, m, sm, eh, error, check, currentK, exactchecking, onlyExactCheckingPermissions, transferPermissionToSecMask, recurseOnPredicatesDepth, isUpdatingSecMask, previousReceivers, duringUnfold)
+ LocalExhaleHelper(e0) ::: LocalExhaleHelper(e1)
case holds@Holds(e) if !onlyExactCheckingPermissions =>
(if(check) isDefined(e)(true) :::
bassert(nonNull(Tr(e)), error.pos, error.message + " The target of the holds predicate at " + holds.pos + " might be null.") :: Nil else Nil) :::
@@ -2417,33 +2760,35 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
bassume(wf(preEtran.Heap, preEtran.Mask, preEtran.SecMask)) ::
bassert(proofOrAssume, p.pos, "Arguments for joinable might not match up.") ::
preEtran.Exhale(List((e, error)), "eval", check, currentK, exactchecking)
- case e if !onlyExactCheckingPermissions => (if(check) isDefined(e)(true) else Nil) ::: List(bassert(Tr(e), error.pos, error.message + " The expression at " + e.pos + " might not evaluate to true."))
+ case e if !onlyExactCheckingPermissions =>
+ val (ee,ll) = Tr(e, true) // keep list ll of statements here, in case we are missing effects from unfolding expressions (if we do not call isDefined(e) below, we won't add secondary permissions/"inside" instances)
+ (if(check) isDefined(e)(true) else ll) ::: List(bassert(ee, error.pos, error.message + " The expression at " + e.pos + " might not evaluate to true."))
case _ => Nil
- }
+ }}
def extractKFromPermission(expr: Permission, currentK: Expr): (Expr, List[Boogie.Stmt]) = expr match {
case Full => (permissionFull, Nil)
case Epsilon => (currentK, Nil)
- case Epsilons(_) => (0, Nil)
+ case Epsilons(_) => (0.0, Nil)
case PredicateEpsilon(_) => (predicateK, Nil)
case MonitorEpsilon(_) => (monitorK, Nil)
case ChannelEpsilon(_) => (channelK, Nil)
case MethodEpsilon => (currentK, Nil)
case ForkEpsilon(token) =>
val fk = etran.Heap.select(Tr(token), forkK)
- (fk, bassume(0 < fk && fk < percentPermission(1)) /* this is always true for forkK */)
+ (fk, bassume(0.0 < fk && fk < percentPermission(1)) /* this is always true for forkK */)
case Star =>
- val (starKV, starK) = NewBVar("starK", tint, true);
- (starK, BLocal(starKV) :: bassume(starK > 0 /* an upper bound is provided later by DecPermission */) :: Nil)
+ val (starKV, starK) = NewBVar("starK", treal, true);
+ (starK, BLocal(starKV) :: bassume(starK > 0.0 /* an upper bound is provided later by DecPermission */) :: Nil)
case Frac(p) => (percentPermission(Tr(p)), Nil)
case IntPermTimes(lhs, rhs) => {
val (r, rs) = extractKFromPermission(rhs, currentK)
- (lhs * r, rs)
+ (int2real(lhs) * r, rs)
}
case PermTimes(lhs, rhs) => {
val (l, ls) = extractKFromPermission(lhs, currentK)
val (r, rs) = extractKFromPermission(rhs, currentK)
- val (resV, res) = Boogie.NewBVar("productK", tint, true)
+ val (resV, res) = Boogie.NewBVar("productK", treal, true)
(res, ls ::: rs ::: BLocal(resV) :: bassume(permissionFull * res ==@ l * r) :: Nil)
}
case PermPlus(lhs, rhs) => {
@@ -2459,10 +2804,10 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
}
def extractEpsilonsFromPermission(expr: Permission): Expr = expr match {
- case _:Write => 0
- case Epsilons(n) => Tr(n)
- case PermTimes(lhs, rhs) => 0 // multiplication cannot give epsilons
- case IntPermTimes(lhs, rhs) => lhs * extractEpsilonsFromPermission(rhs)
+ case _:Write => 0.0
+ case Epsilons(n) => int2real(Tr(n))
+ case PermTimes(lhs, rhs) => 0.0 // multiplication cannot give epsilons
+ case IntPermTimes(lhs, rhs) => int2real(lhs) * extractEpsilonsFromPermission(rhs)
case PermPlus(lhs, rhs) => {
val l = extractEpsilonsFromPermission(lhs)
val r = extractEpsilonsFromPermission(rhs)
@@ -2532,13 +2877,13 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
def CanWrite(obj: Boogie.Expr, field: Boogie.Expr): Boogie.Expr = new Boogie.FunctionApp("CanWrite", Mask, obj, field)
def CanWrite(obj: Boogie.Expr, field: String): Boogie.Expr = CanWrite(obj, new Boogie.VarExpr(field))
def HasNoPermission(obj: Boogie.Expr, field: String) =
- (new Boogie.MapSelect(Mask, obj, field, "perm$R") ==@ Boogie.IntLiteral(0)) &&
- (new Boogie.MapSelect(Mask, obj, field, "perm$N") ==@ Boogie.IntLiteral(0))
+ (new Boogie.MapSelect(Mask, obj, field, "perm$R") ==@ 0.0) &&
+ (new Boogie.MapSelect(Mask, obj, field, "perm$N") ==@ 0.0)
def SetNoPermission(obj: Boogie.Expr, field: String, mask: Boogie.Expr) =
Boogie.Assign(new Boogie.MapSelect(mask, obj, field), Boogie.VarExpr("Permission$Zero"))
def HasFullPermission(obj: Boogie.Expr, field: String, mask: Boogie.Expr) =
(new Boogie.MapSelect(mask, obj, field, "perm$R") ==@ permissionFull) &&
- (new Boogie.MapSelect(mask, obj, field, "perm$N") ==@ Boogie.IntLiteral(0))
+ (new Boogie.MapSelect(mask, obj, field, "perm$N") ==@ 0.0)
def SetFullPermission(obj: Boogie.Expr, field: String) =
Boogie.Assign(new Boogie.MapSelect(Mask, obj, field), Boogie.VarExpr("Permission$Full"))
@@ -2552,13 +2897,13 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
def DecPermission(obj: Boogie.Expr, field: String, howMuch: Boogie.Expr, mask: Boogie.Expr, error: ErrorMessage, pos: Position, exactchecking: Boolean): List[Boogie.Stmt] = {
val fP: Boogie.Expr = new Boogie.MapSelect(mask, obj, field, "perm$R")
val fC: Boogie.Expr = new Boogie.MapSelect(mask, obj, field, "perm$N")
- (if (exactchecking) bassert(howMuch <= fP && (howMuch ==@ fP ==> 0 <= fC), error.pos, error.message + " Insufficient fraction at " + pos + " for " + field + ".") :: Nil
- else bassert(fP > 0, error.pos, error.message + " Insufficient fraction at " + pos + " for " + field + ".") :: bassume(howMuch < fP)) :::
+ (if (exactchecking) bassert(howMuch <= fP && (howMuch ==@ fP ==> 0.0 <= fC), error.pos, error.message + " Insufficient fraction at " + pos + " for " + field + ".") :: Nil
+ else bassert(fP > 0.0, error.pos, error.message + " Insufficient fraction at " + pos + " for " + field + ".") :: bassume(howMuch < fP)) :::
MapUpdate3(mask, obj, field, "perm$R", new Boogie.MapSelect(mask, obj, field, "perm$R") - howMuch)
}
def DecPermissionEpsilon(obj: Boogie.Expr, field: String, epsilons: Boogie.Expr, mask: Boogie.Expr, error: ErrorMessage, pos: Position): List[Boogie.Stmt] = {
val xyz = new Boogie.MapSelect(mask, obj, field, "perm$N")
- bassert((new Boogie.MapSelect(mask, obj, field, "perm$R") ==@ Boogie.IntLiteral(0)) ==> (epsilons <= xyz), error.pos, error.message + " Insufficient epsilons at " + pos + " for " + field + ".") ::
+ bassert((new Boogie.MapSelect(mask, obj, field, "perm$R") ==@ 0.0) ==> (epsilons <= xyz), error.pos, error.message + " Insufficient epsilons at " + pos + " for " + field + ".") ::
MapUpdate3(mask, obj, field, "perm$N", new Boogie.MapSelect(mask, obj, field, "perm$N") - epsilons) ::
bassume(wf(Heap, Mask, SecMask)) :: Nil
}
@@ -2567,30 +2912,30 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F
val fC: Boogie.Expr = new Boogie.MapSelect(mask, obj, field, "perm$N")
(if (exactchecking) bassert(howMuch <= fP && (howMuch ==@ fP ==> epsilons <= fC), error.pos, error.message + " Insufficient permission at " + pos + " for " + field + ".") :: Nil
- else bassert(fP > 0, error.pos, error.message + " Insufficient permission at " + pos + " for " + field + ".") :: bassume(howMuch < fP)) :::
+ else bassert(fP > 0.0, error.pos, error.message + " Insufficient permission at " + pos + " for " + field + ".") :: bassume(howMuch < fP)) :::
MapUpdate3(mask, obj, field, "perm$N", fC - epsilons) ::
MapUpdate3(mask, obj, field, "perm$R", fP - howMuch) ::
bassume(wf(Heap, Mask, SecMask)) :: Nil
}
def DecPermission2(obj: Boogie.Expr, field: String, howMuch: Boogie.Expr, mask: Boogie.Expr, error: ErrorMessage, pos: Position, exactchecking: Boolean): List[Boogie.Stmt] = {
DecPermission(obj, field, howMuch, mask, error, pos, exactchecking) :::
- Boogie.If(new Boogie.MapSelect(mask, obj, field, "perm$R") < 0,
- MapUpdate3(mask, obj, field, "perm$R", 0),
+ Boogie.If(new Boogie.MapSelect(mask, obj, field, "perm$R") < 0.0,
+ MapUpdate3(mask, obj, field, "perm$R", 0.0),
Nil)
}
def DecPermissionEpsilon2(obj: Boogie.Expr, field: String, epsilons: Boogie.Expr, mask: Boogie.Expr, error: ErrorMessage, pos: Position): List[Boogie.Stmt] = {
DecPermissionEpsilon(obj, field, epsilons, mask, error, pos) :::
- Boogie.If(new Boogie.MapSelect(mask, obj, field, "perm$N") < 0,
- MapUpdate3(mask, obj, field, "perm$N", 0),
+ Boogie.If(new Boogie.MapSelect(mask, obj, field, "perm$N") < 0.0,
+ MapUpdate3(mask, obj, field, "perm$N", 0.0),
Nil)
}
def DecPermissionBoth2(obj: Boogie.Expr, field: String, howMuch: Boogie.Expr, epsilons: Boogie.Expr, mask: Boogie.Expr, error: ErrorMessage, pos: Position, exactchecking: Boolean): List[Boogie.Stmt] = {
DecPermissionBoth(obj, field, howMuch, epsilons, mask, error, pos, exactchecking) :::
- Boogie.If(new Boogie.MapSelect(mask, obj, field, "perm$R") < 0,
- MapUpdate3(mask, obj, field, "perm$R", 0),
+ Boogie.If(new Boogie.MapSelect(mask, obj, field, "perm$R") < 0.0,
+ MapUpdate3(mask, obj, field, "perm$R", 0.0),
Nil) ::
- Boogie.If(new Boogie.MapSelect(mask, obj, field, "perm$N") < 0,
- MapUpdate3(mask, obj, field, "perm$N", 0),
+ Boogie.If(new Boogie.MapSelect(mask, obj, field, "perm$N") < 0.0,
+ MapUpdate3(mask, obj, field, "perm$N", 0.0),
Nil) :: Nil
}
@@ -2687,6 +3032,7 @@ object TranslationHelper {
implicit def field2Expr(f: Field) = VarExpr(f.FullName);
implicit def bool2Bool(b: Boolean): Boogie.BoolLiteral = Boogie.BoolLiteral(b)
implicit def int2Int(n: Int): Boogie.IntLiteral = Boogie.IntLiteral(n)
+ implicit def real2Real(d: Double): Boogie.RealLiteral = Boogie.RealLiteral(d)
implicit def lift(s: Boogie.Stmt): List[Boogie.Stmt] = List(s)
implicit def type2BType(cl: Class): BType = {
if(cl.IsRef) {
@@ -2729,15 +3075,18 @@ object TranslationHelper {
def tArgSeq = NamedType("ArgSeq");
def tref = NamedType("ref");
def tbool = NamedType("bool");
+ def treal = NamedType("real");
def tmu = NamedType("Mu");
def tint = NamedType("int");
def tstring = NamedType("string");
def tseq(arg: BType) = IndexedType("Seq", arg)
def theap = NamedType("HeapType");
def tmask = NamedType("MaskType");
+ def tpmask = NamedType("PMaskType");
def tcredits = NamedType("CreditsType");
def tperm = NamedType("PermissionComponent");
def ZeroMask = VarExpr("ZeroMask");
+ def ZeroPMask = VarExpr("ZeroPMask");
def ZeroCredits = VarExpr("ZeroCredits");
def HeapName = "Heap";
def MaskName = "Mask";
@@ -2745,14 +3094,16 @@ object TranslationHelper {
def CreditsName = "Credits";
def GlobalNames = List(HeapName, MaskName, SecMaskName, CreditsName);
def CanAssumeFunctionDefs = VarExpr("CanAssumeFunctionDefs");
+ def FunctionContextHeight = VarExpr("FunctionContextHeight");
def permissionFull = percentPermission(100);
def permissionOnePercent = percentPermission(1);
def percentPermission(e: Expr) = {
Chalice.percentageSupport match {
- case 0 | 1 => e*VarExpr("Permission$denominator")
- case 2 | 3 => FunctionApp("Fractions", List(e))
+ case 0 => int2real(e)*0.01
+ case 1 => FunctionApp("Fractions", List(e))
}
}
+ def int2real(e: Expr): Expr = FunctionApp("real", List(e))
def forkK = "forkK";
def channelK = "channelK";
def monitorK = "monitorK";
@@ -2785,6 +3136,7 @@ object TranslationHelper {
def AreGoodMasks(m: Expr, sm: Expr) = IsGoodMask(m) // && IsGoodMask(sm) /** The second mask does currently not necessarily contain positive permissions, which means that we cannot assume IsGoodMask(sm). This might change in the future if we see a need for it */
def IsGoodInhaleState(ih: Expr, h: Expr, m: Expr, sm: Expr) = FunctionApp("IsGoodInhaleState", List(ih,h,m,sm))
def IsGoodExhaleState(eh: Expr, h: Expr, m: Expr, sm: Expr) = FunctionApp("IsGoodExhaleState", List(eh,h,m,sm))
+ def IsGoodExhalePredicateState(eh: Expr, h: Expr, pm: Expr) = FunctionApp("IsGoodExhalePredicateState", List(eh,h,pm))
def contributesToWaitLevel(e: Expr, h: Expr, c: Expr) =
(0 < h.select(e, "held")) || h.select(e, "rdheld") || (new Boogie.MapSelect(c, e) < 0)
def NonEmptyMask(m: Expr) = ! FunctionApp("EmptyMask", List(m))
@@ -2898,7 +3250,7 @@ object TranslationHelper {
heapFragment(Boogie.Ite(etran.Tr(con), functionDependencies(then, etran), functionDependencies(els, etran)))
case Unfolding(_, _) =>
emptyPartialHeap // the predicate of the unfolding expression needs to have been mentioned already (framing check), so we can safely ignore it now
- case p: PermissionExpr => println(p); throw new InternalErrorException("unexpected permission expression")
+ case p: PermissionExpr => throw new InternalErrorException("unexpected permission expression")
case e =>
e visitOpt {_ match {
case Unfolding(_, _) => false
diff --git a/Chalice/tests/examples/AVLTree.iterative.output.txt b/Chalice/tests/examples/AVLTree.iterative.output.txt
index 152260e3..9b8797ef 100644
--- a/Chalice/tests/examples/AVLTree.iterative.output.txt
+++ b/Chalice/tests/examples/AVLTree.iterative.output.txt
@@ -1,4 +1,4 @@
Verification of AVLTree.iterative.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/AVLTree.nokeys.output.txt b/Chalice/tests/examples/AVLTree.nokeys.output.txt
index c9dc557a..49850add 100644
--- a/Chalice/tests/examples/AVLTree.nokeys.output.txt
+++ b/Chalice/tests/examples/AVLTree.nokeys.output.txt
@@ -1,4 +1,4 @@
Verification of AVLTree.nokeys.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/AssociationList.output.txt b/Chalice/tests/examples/AssociationList.output.txt
index 2955a814..e7ae56f6 100644
--- a/Chalice/tests/examples/AssociationList.output.txt
+++ b/Chalice/tests/examples/AssociationList.output.txt
@@ -7,4 +7,4 @@ Verification of AssociationList.chalice using parameters=""
73.9: The loop might lock/unlock more than the lockchange clause allows.
107.7: Monitor invariant might hot hold. Insufficient fraction at 120.13 for Node.key.
-Boogie program verifier finished with 6 errors and 0 smoke test warnings.
+Boogie program verifier finished with 6 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/BackgroundComputation.output.txt b/Chalice/tests/examples/BackgroundComputation.output.txt
index dc1bafc1..ad3f590e 100644
--- a/Chalice/tests/examples/BackgroundComputation.output.txt
+++ b/Chalice/tests/examples/BackgroundComputation.output.txt
@@ -1,4 +1,4 @@
Verification of BackgroundComputation.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/CopyLessMessagePassing-with-ack.output.txt b/Chalice/tests/examples/CopyLessMessagePassing-with-ack.output.txt
index b47290ea..91c56769 100644
--- a/Chalice/tests/examples/CopyLessMessagePassing-with-ack.output.txt
+++ b/Chalice/tests/examples/CopyLessMessagePassing-with-ack.output.txt
@@ -5,4 +5,4 @@ Verification of CopyLessMessagePassing-with-ack.chalice using parameters=""
69.22: Assumption introduces a contradiction.
72.21: Assumption introduces a contradiction.
-Boogie program verifier finished with 0 errors and 3 smoke test warnings.
+Boogie program verifier finished with 0 errors and 3 smoke test warnings
diff --git a/Chalice/tests/examples/CopyLessMessagePassing-with-ack2.output.txt b/Chalice/tests/examples/CopyLessMessagePassing-with-ack2.output.txt
index 42a63bf1..2d6d752d 100644
--- a/Chalice/tests/examples/CopyLessMessagePassing-with-ack2.output.txt
+++ b/Chalice/tests/examples/CopyLessMessagePassing-with-ack2.output.txt
@@ -4,4 +4,4 @@ Verification of CopyLessMessagePassing-with-ack2.chalice using parameters=""
50.23: Assumption introduces a contradiction.
65.27: Assumption introduces a contradiction.
-Boogie program verifier finished with 0 errors and 2 smoke test warnings.
+Boogie program verifier finished with 0 errors and 2 smoke test warnings
diff --git a/Chalice/tests/examples/CopyLessMessagePassing.output.txt b/Chalice/tests/examples/CopyLessMessagePassing.output.txt
index 26784a86..2caf540b 100644
--- a/Chalice/tests/examples/CopyLessMessagePassing.output.txt
+++ b/Chalice/tests/examples/CopyLessMessagePassing.output.txt
@@ -1,4 +1,4 @@
Verification of CopyLessMessagePassing.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/FictionallyDisjointCells.output.txt b/Chalice/tests/examples/FictionallyDisjointCells.output.txt
index 9bc4fb68..0b8b0c4f 100644
--- a/Chalice/tests/examples/FictionallyDisjointCells.output.txt
+++ b/Chalice/tests/examples/FictionallyDisjointCells.output.txt
@@ -1,4 +1,4 @@
Verification of FictionallyDisjointCells.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/ForkJoin.output.txt b/Chalice/tests/examples/ForkJoin.output.txt
index b1371da7..5ddd0f65 100644
--- a/Chalice/tests/examples/ForkJoin.output.txt
+++ b/Chalice/tests/examples/ForkJoin.output.txt
@@ -1,4 +1,4 @@
Verification of ForkJoin.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/HandOverHand.output.txt b/Chalice/tests/examples/HandOverHand.output.txt
index 5d32ad2e..13ff996a 100644
--- a/Chalice/tests/examples/HandOverHand.output.txt
+++ b/Chalice/tests/examples/HandOverHand.output.txt
@@ -1,4 +1,4 @@
Verification of HandOverHand.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/OwickiGries.output.txt b/Chalice/tests/examples/OwickiGries.output.txt
index 3a9a215b..8235b0f4 100644
--- a/Chalice/tests/examples/OwickiGries.output.txt
+++ b/Chalice/tests/examples/OwickiGries.output.txt
@@ -1,4 +1,4 @@
Verification of OwickiGries.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/PetersonsAlgorithm.output.txt b/Chalice/tests/examples/PetersonsAlgorithm.output.txt
index eddb4927..1be5bf8c 100644
--- a/Chalice/tests/examples/PetersonsAlgorithm.output.txt
+++ b/Chalice/tests/examples/PetersonsAlgorithm.output.txt
@@ -5,4 +5,4 @@ Verification of PetersonsAlgorithm.chalice using parameters=""
34.5: The statements after the while-loop are unreachable.
59.5: The statements after the while-loop are unreachable.
-Boogie program verifier finished with 0 errors and 3 smoke test warnings.
+Boogie program verifier finished with 0 errors and 3 smoke test warnings
diff --git a/Chalice/tests/examples/ProdConsChannel.output.txt b/Chalice/tests/examples/ProdConsChannel.output.txt
index 4d91605c..20a587da 100644
--- a/Chalice/tests/examples/ProdConsChannel.output.txt
+++ b/Chalice/tests/examples/ProdConsChannel.output.txt
@@ -1,4 +1,4 @@
Verification of ProdConsChannel.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/RockBand.output.txt b/Chalice/tests/examples/RockBand.output.txt
index 94f92a6e..f505fdb3 100644
--- a/Chalice/tests/examples/RockBand.output.txt
+++ b/Chalice/tests/examples/RockBand.output.txt
@@ -1,4 +1,4 @@
Verification of RockBand.chalice using parameters="-checkLeaks -defaults -autoFold"
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/Sieve.output.txt b/Chalice/tests/examples/Sieve.output.txt
index 3e5117d3..0e37cd00 100644
--- a/Chalice/tests/examples/Sieve.output.txt
+++ b/Chalice/tests/examples/Sieve.output.txt
@@ -1,4 +1,4 @@
Verification of Sieve.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/Solver.output.txt b/Chalice/tests/examples/Solver.output.txt
index 1ec04d27..7b6882c5 100644
--- a/Chalice/tests/examples/Solver.output.txt
+++ b/Chalice/tests/examples/Solver.output.txt
@@ -1,4 +1,4 @@
Verification of Solver.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/TreeOfWorker.output.txt b/Chalice/tests/examples/TreeOfWorker.output.txt
index 13932da9..fe0c3376 100644
--- a/Chalice/tests/examples/TreeOfWorker.output.txt
+++ b/Chalice/tests/examples/TreeOfWorker.output.txt
@@ -1,4 +1,4 @@
Verification of TreeOfWorker.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/UnboundedThreads.output.txt b/Chalice/tests/examples/UnboundedThreads.output.txt
index ccb4e93c..f8a05ed9 100644
--- a/Chalice/tests/examples/UnboundedThreads.output.txt
+++ b/Chalice/tests/examples/UnboundedThreads.output.txt
@@ -2,4 +2,4 @@ Verification of UnboundedThreads.chalice using parameters=""
40.17: The loop invariant at 40.17 might not be preserved by the loop. Insufficient epsilons at 40.27 for C.f.
-Boogie program verifier finished with 1 errors and 0 smoke test warnings.
+Boogie program verifier finished with 1 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/cell.output.txt b/Chalice/tests/examples/cell.output.txt
index b5ba1586..b1567d01 100644
--- a/Chalice/tests/examples/cell.output.txt
+++ b/Chalice/tests/examples/cell.output.txt
@@ -5,4 +5,4 @@ Verification of cell.chalice using parameters=""
The program did not fully verify; the smoke warnings might be misleading if contradictions are introduced by failing proof attempts of the verification.
135.3: The end of method main2 is unreachable.
-Boogie program verifier finished with 1 errors and 1 smoke test warnings.
+Boogie program verifier finished with 1 errors and 1 smoke test warnings
diff --git a/Chalice/tests/examples/dining-philosophers.output.txt b/Chalice/tests/examples/dining-philosophers.output.txt
index bd1bd4a0..ffba722f 100644
--- a/Chalice/tests/examples/dining-philosophers.output.txt
+++ b/Chalice/tests/examples/dining-philosophers.output.txt
@@ -3,4 +3,4 @@ Verification of dining-philosophers.chalice using parameters=""
24.5: The statements after the while-loop are unreachable.
-Boogie program verifier finished with 0 errors and 1 smoke test warnings.
+Boogie program verifier finished with 0 errors and 1 smoke test warnings
diff --git a/Chalice/tests/examples/iterator.output.txt b/Chalice/tests/examples/iterator.output.txt
index a33f44db..36a72bac 100644
--- a/Chalice/tests/examples/iterator.output.txt
+++ b/Chalice/tests/examples/iterator.output.txt
@@ -1,4 +1,4 @@
Verification of iterator.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/iterator2.output.txt b/Chalice/tests/examples/iterator2.output.txt
index 02a7f02d..a28c5785 100644
--- a/Chalice/tests/examples/iterator2.output.txt
+++ b/Chalice/tests/examples/iterator2.output.txt
@@ -1,4 +1,4 @@
Verification of iterator2.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/linkedlist.chalice b/Chalice/tests/examples/linkedlist.chalice
index acde86ab..a9859aaa 100644
--- a/Chalice/tests/examples/linkedlist.chalice
+++ b/Chalice/tests/examples/linkedlist.chalice
@@ -6,7 +6,7 @@ class Node {
method init(v: int)
requires acc(next) && acc(value);
- ensures valid && size() == 1;
+ ensures valid && size() == 1 && (forall y:int :: contains(y) <==> y==v);
{
next := null;
value := v;
@@ -17,6 +17,7 @@ class Node {
requires valid;
ensures valid;
ensures size() == old(size())+1;
+ ensures (forall y:int :: contains(y)==(old(contains(y)) || x==y));
{
unfold this.valid;
if(next==null) {
@@ -24,11 +25,32 @@ class Node {
n := new Node;
call n.init(x);
next := n;
+ // unfold next.valid; fold next.valid; // makes it work
} else {
+
call next.add(x);
}
fold this.valid;
}
+
+ method addother(i:int)
+ requires valid
+ ensures valid && (forall x:int :: contains(x)==(old(contains(x)) || x==i))
+ {
+ unfold valid
+ if(next!=null)
+ {
+ call next.addother(i)
+ }
+ else
+ {
+ next:=new Node
+ next.value:=i
+ next.next:=null
+ fold next.valid
+ }
+ fold valid
+ }
method addFirst(x: int) returns (rt: Node)
requires valid;
@@ -46,14 +68,22 @@ class Node {
function at(i: int): int
requires valid && 0<=i && i<size();
{
- unfolding valid in i==0 ? value : next.at(i-1) // no warning anymore... fishy!
+ unfolding valid in i==0 ? value : next.at(i-1)
}
function size(): int
requires valid;
+ ensures result > 0
{
unfolding this.valid in (next!=null ? 1+ next.size() : 1)
}
+
+ function contains(i:int):bool
+ requires valid
+ {
+ unfolding valid in i==value || (next!=null && next.contains(i))
+ }
+
predicate valid {
acc(next) && acc(value) && (next!=null ==> next.valid)
diff --git a/Chalice/tests/examples/linkedlist.output.txt b/Chalice/tests/examples/linkedlist.output.txt
index ce5b5844..ffb5327d 100644
--- a/Chalice/tests/examples/linkedlist.output.txt
+++ b/Chalice/tests/examples/linkedlist.output.txt
@@ -1,5 +1,4 @@
Verification of linkedlist.chalice using parameters=""
- 49.39: Precondition at 47.14 might not hold. The expression at 47.31 might not evaluate to true.
-Boogie program verifier finished with 1 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/list-reverse.output.txt b/Chalice/tests/examples/list-reverse.output.txt
index d8e19122..6179841d 100644
--- a/Chalice/tests/examples/list-reverse.output.txt
+++ b/Chalice/tests/examples/list-reverse.output.txt
@@ -1,4 +1,4 @@
Verification of list-reverse.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/lseg.chalice b/Chalice/tests/examples/lseg.chalice
new file mode 100644
index 00000000..c7b6421a
--- /dev/null
+++ b/Chalice/tests/examples/lseg.chalice
@@ -0,0 +1,86 @@
+class Node {
+ var next : Node;
+ var val : int;
+ /* ghost */ var length : int;
+
+ predicate lseg {
+ acc(length) && length > 0 && acc(next) && acc(val) && (length > 1 ==> next != null && next.lseg && next.lseg_length() + 1 == this.length)
+ }
+
+ function lseg_length() : int
+ requires lseg
+ {
+ unfolding lseg in length
+ }
+
+ function elems() : seq<int>
+ requires lseg
+ {
+ unfolding lseg in (length == 1 ? [val] : [val] ++ next.elems())
+ }
+
+ function end() : Node
+ requires lseg
+ {
+ unfolding lseg in (length == 1 ? next : next.end())
+ }
+
+ /* ghost */ method addAtEndRec(n:Node)
+ requires lseg && acc(n.*)
+ ensures lseg
+ ensures elems() == old(elems()) ++ [old(n.val)]
+ ensures end() == old(n.next)
+ ensures lseg_length() == old(lseg_length()) + 1
+ {
+ unfold this.lseg;
+ if (length == 1) {
+ this.next := n
+ n.length := 1
+ fold n.lseg
+ } else {
+ call this.next.addAtEndRec(n)
+ }
+ this.length := this.length + 1
+ fold this.lseg
+ }
+
+ method addAtEnd(v: int)
+ requires lseg
+ requires this.end() == null
+ ensures lseg
+ ensures elems() == old(elems()) ++ [v]
+ {
+ var cur: Node := this
+ unfold lseg
+ while (cur.next != null)
+ invariant acc(cur.*)
+ invariant this != cur ==> this.lseg && this.end() == cur
+ invariant cur.length > 0 && (cur.length > 1 ==> cur.next != null && cur.next.lseg) && (cur.length == 1 ? cur.next : cur.next.end()) == null
+ invariant ((this == cur ? [] : this.elems())
+ ++ [cur.val]
+ ++ (cur.next == null ? [] : cur.next.elems())) == old(this.elems())
+ {
+ /* ghost */ var temp: Node := cur
+ cur := cur.next
+ if (this == temp) {
+ this.length := 1
+ fold lseg
+ } else {
+ call addAtEndRec(temp)
+ }
+ unfold cur.lseg
+ }
+
+ var n: Node := new Node
+ n.val := v
+ n.next := null
+ cur.next := n
+ if(cur == this) {
+ this.length := 1
+ fold lseg
+ } else {
+ call addAtEndRec(cur)
+ }
+ call addAtEndRec(n)
+ }
+} \ No newline at end of file
diff --git a/Chalice/tests/examples/lseg.output.txt b/Chalice/tests/examples/lseg.output.txt
new file mode 100644
index 00000000..ed31a673
--- /dev/null
+++ b/Chalice/tests/examples/lseg.output.txt
@@ -0,0 +1,4 @@
+Verification of lseg.chalice using parameters=""
+
+
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/examples/producer-consumer.output.txt b/Chalice/tests/examples/producer-consumer.output.txt
index 55f4bf3c..f3c3a28a 100644
--- a/Chalice/tests/examples/producer-consumer.output.txt
+++ b/Chalice/tests/examples/producer-consumer.output.txt
@@ -4,4 +4,4 @@ Verification of producer-consumer.chalice using parameters=""
42.5: The statements after the while-loop are unreachable.
81.5: The statements after the while-loop are unreachable.
-Boogie program verifier finished with 0 errors and 2 smoke test warnings.
+Boogie program verifier finished with 0 errors and 2 smoke test warnings
diff --git a/Chalice/tests/examples/swap.output.txt b/Chalice/tests/examples/swap.output.txt
index 8cd3bb7c..c0e86b2a 100644
--- a/Chalice/tests/examples/swap.output.txt
+++ b/Chalice/tests/examples/swap.output.txt
@@ -1,4 +1,4 @@
Verification of swap.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/general-tests/FunctionPostcondition.chalice b/Chalice/tests/general-tests/FunctionPostcondition.chalice
new file mode 100644
index 00000000..7fd95b05
--- /dev/null
+++ b/Chalice/tests/general-tests/FunctionPostcondition.chalice
@@ -0,0 +1,10 @@
+// this test is for function postconditions
+
+class FunctionPostconditions
+{
+ predicate valid { true }
+
+ function t1(): int
+ ensures unfolding valid in true;
+ { 1 }
+}
diff --git a/Chalice/tests/general-tests/FunctionPostcondition.output.txt b/Chalice/tests/general-tests/FunctionPostcondition.output.txt
new file mode 100644
index 00000000..3244dc57
--- /dev/null
+++ b/Chalice/tests/general-tests/FunctionPostcondition.output.txt
@@ -0,0 +1,4 @@
+Verification of FunctionPostcondition.chalice using parameters=""
+
+The program did not typecheck.
+8.5: the postcondition of functions cannot contain unfolding expressions at the moment
diff --git a/Chalice/tests/general-tests/ImplicitLocals.output.txt b/Chalice/tests/general-tests/ImplicitLocals.output.txt
index db26bba6..8e59a2b0 100644
--- a/Chalice/tests/general-tests/ImplicitLocals.output.txt
+++ b/Chalice/tests/general-tests/ImplicitLocals.output.txt
@@ -1,4 +1,4 @@
Verification of ImplicitLocals.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/general-tests/LoopLockChange.output.txt b/Chalice/tests/general-tests/LoopLockChange.output.txt
index 19e84f93..ccd9a36a 100644
--- a/Chalice/tests/general-tests/LoopLockChange.output.txt
+++ b/Chalice/tests/general-tests/LoopLockChange.output.txt
@@ -9,4 +9,4 @@ The program did not fully verify; the smoke warnings might be misleading if cont
10.5: The statements after the while-loop are unreachable.
75.5: Assumption introduces a contradiction.
-Boogie program verifier finished with 3 errors and 3 smoke test warnings.
+Boogie program verifier finished with 3 errors and 3 smoke test warnings
diff --git a/Chalice/tests/general-tests/RockBand-automagic.output.txt b/Chalice/tests/general-tests/RockBand-automagic.output.txt
index 2e62b457..652213d9 100644
--- a/Chalice/tests/general-tests/RockBand-automagic.output.txt
+++ b/Chalice/tests/general-tests/RockBand-automagic.output.txt
@@ -1,4 +1,4 @@
Verification of RockBand-automagic.chalice using parameters="-checkLeaks -defaults -autoFold -autoMagic"
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/general-tests/SmokeTestTest.output.txt b/Chalice/tests/general-tests/SmokeTestTest.output.txt
index 3d1cd786..1ad5f926 100644
--- a/Chalice/tests/general-tests/SmokeTestTest.output.txt
+++ b/Chalice/tests/general-tests/SmokeTestTest.output.txt
@@ -20,4 +20,4 @@ The program did not fully verify; the smoke warnings might be misleading if cont
116.3: Predicate Cell.valid is equivalent to false.
121.1: Where clause of channel C is equivalent to false.
-Boogie program verifier finished with 1 errors and 16 smoke test warnings.
+Boogie program verifier finished with 1 errors and 16 smoke test warnings
diff --git a/Chalice/tests/general-tests/cell-defaults.output.txt b/Chalice/tests/general-tests/cell-defaults.output.txt
index 138a5717..fd748230 100644
--- a/Chalice/tests/general-tests/cell-defaults.output.txt
+++ b/Chalice/tests/general-tests/cell-defaults.output.txt
@@ -7,4 +7,4 @@ Verification of cell-defaults.chalice using parameters="-defaults -autoFold -aut
The program did not fully verify; the smoke warnings might be misleading if contradictions are introduced by failing proof attempts of the verification.
125.3: The end of method main2 is unreachable.
-Boogie program verifier finished with 3 errors and 1 smoke test warnings.
+Boogie program verifier finished with 3 errors and 1 smoke test warnings
diff --git a/Chalice/tests/general-tests/counter.output.txt b/Chalice/tests/general-tests/counter.output.txt
index 3c7f78b0..53bcd98d 100644
--- a/Chalice/tests/general-tests/counter.output.txt
+++ b/Chalice/tests/general-tests/counter.output.txt
@@ -14,4 +14,4 @@ The program did not fully verify; the smoke warnings might be misleading if cont
137.7: The begging of the lock-block is unreachable.
142.3: The end of method nestedBad3 is unreachable.
-Boogie program verifier finished with 6 errors and 5 smoke test warnings.
+Boogie program verifier finished with 6 errors and 5 smoke test warnings
diff --git a/Chalice/tests/general-tests/ll-lastnode.chalice b/Chalice/tests/general-tests/ll-lastnode.chalice
new file mode 100644
index 00000000..f7a44cfe
--- /dev/null
+++ b/Chalice/tests/general-tests/ll-lastnode.chalice
@@ -0,0 +1,82 @@
+// This test case showed a triggering problem (and potentially a matching loop).
+// The quantified assertion and postcondition that did not verify are highlighted below.
+class Node
+{
+ var val:int
+ var next:Node
+ var break_here:bool
+
+ predicate lseg
+ {
+ acc(break_here) && (!break_here ==> acc(val) && acc(next) && (next!=null ==> next.lseg))
+ }
+
+ predicate xlseg
+ {
+ acc(val) && acc(next) && (next!=null ==> next.lseg)
+ }
+
+ function length():int
+ requires lseg
+ ensures 0 <= result
+ {
+ unfolding lseg in (break_here ? 0 : (next==null ? 1 : 1+next.length()))
+ }
+
+ function xlength():int
+ requires xlseg
+ ensures 0 < result
+ {
+ unfolding xlseg in (next==null ? 1 : 1+next.length())
+ }
+
+ function get(i:int):int
+ requires lseg && i>=0 && i<length()
+ {
+ unfolding lseg in i==0 ? val : next.get(i-1)
+ }
+
+ function xget(i:int):int
+ requires xlseg && i>=0 && i<xlength()
+ {
+ unfolding xlseg in i==0 ? val : next.get(i-1)
+ }
+
+ function get_next_seg():Node
+ requires lseg
+ {
+ unfolding lseg in break_here ? this : (next==null ? next : next.get_next_seg())
+ }
+
+ method lastNode() returns(res:Node)
+ requires lseg && length()>0
+ ensures res != null && lseg && res.xlseg
+ ensures res.xlength()==1 && res.xget(0)==old(get(length()-1))
+ ensures length() == old(length()-1)
+ // Did not verify.
+ ensures (forall i:int :: 0<=i && i<length() ==> get(i) == old(get(i)))
+ {
+ var I:int
+ var h:Node
+
+ res:=this
+ unfold lseg
+ break_here:=true
+ fold lseg
+ fold xlseg
+
+ while(res.xlength()>1)
+ invariant res!=null && lseg && res.xlseg &&
+ res==get_next_seg() && // new invariant
+ length() + res.xlength() == old(length()) &&
+ 0 <= length() && length() < old(length()) &&
+ (forall i:int :: 0<=i && i<length() ==> get(i)==old(get(i))) &&
+ (forall i:int :: length()<=i && i<old(length()) ==> res.xget(i-length())==old(get(i)))
+ {
+ // We are not interested (at the moment) in verifying the loop.
+ assume false
+ }
+ // Did not verify.
+ assert (forall i:int :: length()<=i && i<old(length()) ==> res.xget(i-length())==old(get(i)))
+ }
+} \ No newline at end of file
diff --git a/Chalice/tests/general-tests/ll-lastnode.output.txt b/Chalice/tests/general-tests/ll-lastnode.output.txt
new file mode 100644
index 00000000..a02dd2d8
--- /dev/null
+++ b/Chalice/tests/general-tests/ll-lastnode.output.txt
@@ -0,0 +1,6 @@
+Verification of ll-lastnode.chalice using parameters=""
+
+
+ 77.9: Assumption introduces a contradiction.
+
+Boogie program verifier finished with 0 errors and 1 smoke test warnings
diff --git a/Chalice/tests/general-tests/nestedPredicates.chalice b/Chalice/tests/general-tests/nestedPredicates.chalice
new file mode 100644
index 00000000..8afbff5c
--- /dev/null
+++ b/Chalice/tests/general-tests/nestedPredicates.chalice
@@ -0,0 +1,114 @@
+/* Recursive implementation and specification of a linked list. */
+
+class Node {
+ var next: Node;
+ var value: int;
+
+ predicate valid {
+ rd*(next) && rd*(value) && (next!=null ==> next.valid)
+ }
+
+ method testNestingUnfold()
+ requires acc(this.valid)
+ {
+ unfold this.valid;
+ assert this != this.next;
+ if(this.next != null) {
+ unfold this.next.valid;
+ assert this.next != this.next.next;
+ assert this != this.next.next;
+ }
+ }
+
+ method testNestingFold() // this test shows that we build in the assumption that predicate instances with infinite expansions cannot be exist (in reachable code)
+ requires rd*(this.next) && rd*(this.value) && rd*(this.next.next) && rd*(this.next.value) && this.next != null && this.next.next != null && this.next.next.valid
+
+ {
+ fold this.next.valid;
+ assert this.next != this.next.next; // definition of valid "proves" that this.next and this.next.next cannot be aliases
+ fold this.valid;
+ assert this != this.next;
+ assert this != this.next.next;
+ }
+
+ method testNestingUnfolding()
+ requires acc(this.valid)
+ {
+ assert this != (unfolding this.valid in this.next);
+ if((unfolding this.valid in this.next) != null) {
+ assert (unfolding this.valid in this.next) != (unfolding this.valid in (unfolding this.next.valid in this.next.next));
+ assert this != (unfolding this.valid in (unfolding this.next.valid in this.next.next));
+ }
+ }
+
+ predicate p {
+ rd*(next) && rd*(value) && (next!=null ==> next.q)
+ }
+
+ predicate q {
+ rd*(next) && rd*(value) && (next!=null ==> next.p)
+ }
+
+ method testNestingUnfoldTwo()
+ requires acc(this.p)
+ {
+ unfold this.p;
+ assert this != this.next; // should fail
+ if(this.next != null) {
+ unfold this.next.q;
+ assert this.next != this.next.next; // should fail
+ assert this != this.next.next; // should succeed
+ }
+ }
+
+ method testNestingFoldTwo() // this test shows that we build in the assumption that predicate instances with infinite expansions cannot be exist (in reachable code)
+ requires rd*(this.next) && rd*(this.value) && rd*(this.next.next) && rd*(this.next.value) && this.next != null && this.next.next != null && this.next.next.p
+
+ {
+ fold this.next.q;
+ assert this != this.next; // should fail
+ assert this.next != this.next.next; // should fail
+ assert this != this.next.next; // should fail
+ }
+
+ method testNestingFoldThree() // this test shows that we build in the assumption that predicate instances with infinite expansions cannot be exist (in reachable code)
+ requires rd*(this.next) && rd*(this.value) && rd*(this.next.next) && rd*(this.next.value) && this.next != null && this.next.next != null && this.next.next.p
+
+ {
+ fold this.next.q;
+ fold this.p;
+ assert this != this.next; // should succeed, since this == this.next ==> this == this.next.next
+ assert this.next != this.next.next; // should fail - we haven't seen a cycle which would follow from this fact
+ assert this != this.next.next; // should succeed
+ }
+
+ method testNestingUnfoldingTwo()
+ requires acc(this.p)
+ {
+ assert this != (unfolding this.p in this.next); // should fail
+ if((unfolding this.p in this.next) != null) {
+ assert (unfolding this.p in this.next) != (unfolding this.p in (unfolding this.next.q in this.next.next)); // should fail
+ assert this != (unfolding this.p in (unfolding this.next.q in this.next.next)); // should succeed
+ }
+ }
+
+ method testNestingUnfoldingPrecondition(x: Node)
+ requires acc(this.valid) && (unfolding this.valid in this.next == x);
+ {
+ assert this != x;
+ }
+
+ function getNext() : Node
+ requires this.valid;
+ {
+ unfolding this.valid in this.next
+ }
+
+ method testNestingUnfoldingPostcondition(x: Node)
+ requires acc(this.valid);
+ ensures acc(this.valid) && (unfolding this.valid in true) && this != this.getNext()
+ {
+ // nothing
+ }
+
+} \ No newline at end of file
diff --git a/Chalice/tests/general-tests/nestedPredicates.output.txt b/Chalice/tests/general-tests/nestedPredicates.output.txt
new file mode 100644
index 00000000..635ae780
--- /dev/null
+++ b/Chalice/tests/general-tests/nestedPredicates.output.txt
@@ -0,0 +1,12 @@
+Verification of nestedPredicates.chalice using parameters=""
+
+ 56.7: Assertion might not hold. The expression at 56.14 might not evaluate to true.
+ 59.9: Assertion might not hold. The expression at 59.16 might not evaluate to true.
+ 69.7: Assertion might not hold. The expression at 69.14 might not evaluate to true.
+ 70.7: Assertion might not hold. The expression at 70.14 might not evaluate to true.
+ 71.7: Assertion might not hold. The expression at 71.14 might not evaluate to true.
+ 81.7: Assertion might not hold. The expression at 81.14 might not evaluate to true.
+ 88.7: Assertion might not hold. The expression at 88.14 might not evaluate to true.
+ 90.9: Assertion might not hold. The expression at 90.16 might not evaluate to true.
+
+Boogie program verifier finished with 8 errors and 0 smoke test warnings
diff --git a/Chalice/tests/general-tests/prog1.output.txt b/Chalice/tests/general-tests/prog1.output.txt
index 630ecdfa..c6c5fe0e 100644
--- a/Chalice/tests/general-tests/prog1.output.txt
+++ b/Chalice/tests/general-tests/prog1.output.txt
@@ -16,4 +16,4 @@ The program did not fully verify; the smoke warnings might be misleading if cont
73.3: The end of method main5 is unreachable.
78.3: The end of method main6 is unreachable.
-Boogie program verifier finished with 7 errors and 6 smoke test warnings.
+Boogie program verifier finished with 7 errors and 6 smoke test warnings
diff --git a/Chalice/tests/general-tests/prog2.output.txt b/Chalice/tests/general-tests/prog2.output.txt
index 68cd4870..da8dcf22 100644
--- a/Chalice/tests/general-tests/prog2.output.txt
+++ b/Chalice/tests/general-tests/prog2.output.txt
@@ -9,4 +9,4 @@ The program did not fully verify; the smoke warnings might be misleading if cont
20.3: The end of method Caller1 is unreachable.
69.3: The end of method M2 is unreachable.
-Boogie program verifier finished with 4 errors and 2 smoke test warnings.
+Boogie program verifier finished with 4 errors and 2 smoke test warnings
diff --git a/Chalice/tests/general-tests/prog3.output.txt b/Chalice/tests/general-tests/prog3.output.txt
index 18d05658..286b9248 100644
--- a/Chalice/tests/general-tests/prog3.output.txt
+++ b/Chalice/tests/general-tests/prog3.output.txt
@@ -8,4 +8,4 @@ Verification of prog3.chalice using parameters=""
The program did not fully verify; the smoke warnings might be misleading if contradictions are introduced by failing proof attempts of the verification.
191.5: The statements after the method call statement are unreachable.
-Boogie program verifier finished with 4 errors and 1 smoke test warnings.
+Boogie program verifier finished with 4 errors and 1 smoke test warnings
diff --git a/Chalice/tests/general-tests/prog4.output.txt b/Chalice/tests/general-tests/prog4.output.txt
index 9415df7c..4ab057dd 100644
--- a/Chalice/tests/general-tests/prog4.output.txt
+++ b/Chalice/tests/general-tests/prog4.output.txt
@@ -11,4 +11,4 @@ Verification of prog4.chalice using parameters=""
The program did not fully verify; the smoke warnings might be misleading if contradictions are introduced by failing proof attempts of the verification.
2.3: The end of method M is unreachable.
-Boogie program verifier finished with 7 errors and 1 smoke test warnings.
+Boogie program verifier finished with 7 errors and 1 smoke test warnings
diff --git a/Chalice/tests/general-tests/quantifiers.output.txt b/Chalice/tests/general-tests/quantifiers.output.txt
index 2f325c42..f05847b6 100644
--- a/Chalice/tests/general-tests/quantifiers.output.txt
+++ b/Chalice/tests/general-tests/quantifiers.output.txt
@@ -2,4 +2,4 @@ Verification of quantifiers.chalice using parameters=""
57.29: The heap of the callee might not be strictly smaller than the heap of the caller.
-Boogie program verifier finished with 1 errors and 0 smoke test warnings.
+Boogie program verifier finished with 1 errors and 0 smoke test warnings
diff --git a/Chalice/tests/general-tests/triggers.chalice b/Chalice/tests/general-tests/triggers.chalice
new file mode 100644
index 00000000..08a6a7dd
--- /dev/null
+++ b/Chalice/tests/general-tests/triggers.chalice
@@ -0,0 +1,81 @@
+// this test is for the automatic trigger generation
+
+class Triggers
+{
+ var next : Triggers // to allow recursive definitions
+
+ predicate valid { acc(next) && next != null && next.valid } // intentionally doesn't terminate - allows function definitions to be unknown
+
+ function f(x,y,z : int):bool
+ requires valid
+ {
+ unfolding valid in next.f(x,y,z) // unknown definition
+ }
+
+ function h(x,y,z : int):bool
+ requires valid
+ {
+ unfolding valid in next.h(x,y,z) // unknown definition
+ }
+
+ function g(x : int) : bool
+ requires valid
+ {
+ unfolding valid in next.g(x) // unknown definition
+ }
+
+ function i(x:int, y:bool) : bool
+ requires valid
+ {
+ unfolding valid in next.i(x,y) // unknown definition
+ }
+
+
+ method triggers_one()
+ requires valid
+ requires (forall a : int :: !(g(a) ==> false))
+ ensures valid
+ ensures (forall b : int :: g(b))
+ { }
+
+ method triggers_two()
+ requires valid
+ requires (forall a,b,c : int :: ( g(a) && f(a,b,c)))
+ ensures valid
+ ensures (forall x,y,z : int :: f(x,y,z))
+ ensures (forall w : int :: (g(w))) // fails because there isn't a good enough trigger for finding g(w)
+ { }
+
+ method triggers_three()
+ requires valid
+ requires (forall a : int :: ( g(a) && (forall b,c : int :: f(a,b,c))))
+ ensures valid
+ ensures (forall x,y,z : int :: f(x,y,z)) // fails because of the trigger chosen for a (g(a)).
+ ensures (forall w : int :: (g(w)))
+ { }
+
+ method triggers_four()
+ requires valid
+ requires (forall a,b,c,d,e:int :: f(a,b,c) && h(b,c,d) && f(c,d,e))
+ ensures valid
+ ensures (forall x,y,z : int :: f(x,y,z)) // fails - not enough triggers
+ ensures (forall x,y,z : int :: f(x,y,z) && f(z,y,x)) // succeeds - {f(a,b,c),f(c,d,e)} is one of the trigger sets which should be found
+ { }
+
+ method triggers_five(c : bool, d : bool)
+ requires c ==> d
+ requires valid
+ requires (forall x : int :: i(x, (c ==> d))) // check that logical operators are suitably avoided in triggers
+ ensures valid
+ ensures i(4,true)
+ { }
+
+ method triggers_six(c : int, d : int)
+ requires c > d
+ requires valid
+ requires (forall x : int :: i(x, (c > d))) // check that logical operators are suitably avoided in triggers
+ ensures valid
+ ensures i(4,true)
+ { }
+
+} \ No newline at end of file
diff --git a/Chalice/tests/general-tests/triggers.output.txt b/Chalice/tests/general-tests/triggers.output.txt
new file mode 100644
index 00000000..3fae3c21
--- /dev/null
+++ b/Chalice/tests/general-tests/triggers.output.txt
@@ -0,0 +1,7 @@
+Verification of triggers.chalice using parameters=""
+
+ 41.3: The postcondition at 46.14 might not hold. The expression at 46.14 might not evaluate to true.
+ 49.3: The postcondition at 53.14 might not hold. The expression at 53.14 might not evaluate to true.
+ 57.3: The postcondition at 61.14 might not hold. The expression at 61.14 might not evaluate to true.
+
+Boogie program verifier finished with 3 errors and 0 smoke test warnings
diff --git a/Chalice/tests/permission-model/basic.output.txt b/Chalice/tests/permission-model/basic.output.txt
index 02e7acb7..b2bf49bd 100644
--- a/Chalice/tests/permission-model/basic.output.txt
+++ b/Chalice/tests/permission-model/basic.output.txt
@@ -5,4 +5,4 @@ Verification of basic.chalice using parameters=""
97.3: The postcondition at 99.13 might not hold. Insufficient fraction at 99.13 for Cell.x.
148.3: The postcondition at 150.13 might not hold. Insufficient fraction at 150.13 for Cell.x.
-Boogie program verifier finished with 4 errors and 0 smoke test warnings.
+Boogie program verifier finished with 4 errors and 0 smoke test warnings
diff --git a/Chalice/tests/permission-model/channels.output.txt b/Chalice/tests/permission-model/channels.output.txt
index 159e0ee6..b2f76ab6 100644
--- a/Chalice/tests/permission-model/channels.output.txt
+++ b/Chalice/tests/permission-model/channels.output.txt
@@ -3,4 +3,4 @@ Verification of channels.chalice using parameters=""
8.5: The where clause at 44.24 might not hold. Insufficient fraction at 44.24 for C.f.
18.3: The postcondition at 20.13 might not hold. Insufficient fraction at 20.13 for C.f.
-Boogie program verifier finished with 2 errors and 0 smoke test warnings.
+Boogie program verifier finished with 2 errors and 0 smoke test warnings
diff --git a/Chalice/tests/permission-model/locks.output.txt b/Chalice/tests/permission-model/locks.output.txt
index b6ea8f80..6b3a7abe 100644
--- a/Chalice/tests/permission-model/locks.output.txt
+++ b/Chalice/tests/permission-model/locks.output.txt
@@ -17,4 +17,4 @@ The program did not fully verify; the smoke warnings might be misleading if cont
86.3: The end of method a3 is unreachable.
138.5: The statements after the acquire statement are unreachable.
-Boogie program verifier finished with 10 errors and 4 smoke test warnings.
+Boogie program verifier finished with 10 errors and 4 smoke test warnings
diff --git a/Chalice/tests/permission-model/peculiar.output.txt b/Chalice/tests/permission-model/peculiar.output.txt
index e2e6ec90..07104e77 100644
--- a/Chalice/tests/permission-model/peculiar.output.txt
+++ b/Chalice/tests/permission-model/peculiar.output.txt
@@ -5,4 +5,4 @@ Verification of peculiar.chalice using parameters=""
The program did not fully verify; the smoke warnings might be misleading if contradictions are introduced by failing proof attempts of the verification.
30.3: The end of method t4 is unreachable.
-Boogie program verifier finished with 1 errors and 1 smoke test warnings.
+Boogie program verifier finished with 1 errors and 1 smoke test warnings
diff --git a/Chalice/tests/permission-model/permission_arithmetic.output.txt b/Chalice/tests/permission-model/permission_arithmetic.output.txt
index f5c02b3d..b9d20e08 100644
--- a/Chalice/tests/permission-model/permission_arithmetic.output.txt
+++ b/Chalice/tests/permission-model/permission_arithmetic.output.txt
@@ -19,4 +19,4 @@ The program did not fully verify; the smoke warnings might be misleading if cont
200.3: The end of method a28 is unreachable.
215.3: The end of method a28b is unreachable.
-Boogie program verifier finished with 11 errors and 5 smoke test warnings.
+Boogie program verifier finished with 11 errors and 5 smoke test warnings
diff --git a/Chalice/tests/permission-model/predicates.output.txt b/Chalice/tests/permission-model/predicates.output.txt
index 5c0d0455..2f4acf7b 100644
--- a/Chalice/tests/permission-model/predicates.output.txt
+++ b/Chalice/tests/permission-model/predicates.output.txt
@@ -8,4 +8,4 @@ The program did not fully verify; the smoke warnings might be misleading if cont
28.3: The end of method b3 is unreachable.
49.3: The end of method b5 is unreachable.
-Boogie program verifier finished with 3 errors and 2 smoke test warnings.
+Boogie program verifier finished with 3 errors and 2 smoke test warnings
diff --git a/Chalice/tests/permission-model/scaling.chalice b/Chalice/tests/permission-model/scaling.chalice
index 91c73f6d..ffe9aac1 100644
--- a/Chalice/tests/permission-model/scaling.chalice
+++ b/Chalice/tests/permission-model/scaling.chalice
@@ -1,18 +1,3 @@
-/*
-
-Note: At the moment, there is a performance problem if permissions are scaled.
-If a predicate (such as read1 below) contains a read permission, and one takes
-read access to that predicate (as in method s1; rd(read1)), then this
-effectively means that the fractions corresponding to the two read permissions
-are multiplied. This introduces non-linear arithmetic in Boogie, which can be
-very hard and unpredicable for the theorem prover. For this reason, this test is
-taking a very long time to complete.
-
-Note 2: For the moment, this test is (mostly) disabled.
-
--- Stefan Heule, June 2011
-
-*/
class Cell {
var x: int;
@@ -28,59 +13,59 @@ class Cell {
// --- permission scaling ---
method s1()
- // requires rd(read1);
+ requires rd(read1);
{
- // unfold rd(read1);
- // assert(rd*(x));
- // assert(rd(x)); // ERROR: should fail
+ unfold rd(read1);
+ assert(rd*(x));
+ assert(rd(x)); // ERROR: should fail
}
method s2() // INCOMPLETNESS: postcondition should hold, but fails at the moment
- // requires rd(read1);
- // ensures rd(read1);
+ requires rd(read1);
+ ensures rd(read1);
{
- // unfold rd(read1);
- // fold rd(read1);
+ unfold rd(read1);
+ fold rd(read1);
}
method s3()
- // requires acc(x);
- // ensures rd(read1);
+ requires acc(x);
+ ensures rd(read1);
{
- // fold rd(read1);
- // assert(rd*(x));
- // assert(acc(x)); // ERROR: should fail
+ fold rd(read1);
+ assert(rd*(x));
+ assert(acc(x)); // ERROR: should fail
}
method s4() // ERROR: postcondition does not hold
- // requires acc(x);
- // ensures read1;
+ requires acc(x);
+ ensures read1;
{
- // fold rd(read1);
+ fold rd(read1);
}
method s5()
- // requires rd(read2);
+ requires rd(read2);
{
- // unfold rd(read2);
- // assert(rd*(x));
- // assert(rd(x)); // ERROR: should fail
+ unfold rd(read2);
+ assert(rd*(x));
+ assert(rd(x)); // ERROR: should fail
}
method s6()
- // requires acc(x);
- // ensures rd(read2);
+ requires acc(x);
+ ensures rd(read2);
{
- // fold rd(read2);
- // assert(rd*(x));
- // assert(acc(x)); // ERROR: should fail
+ fold rd(read2);
+ assert(rd*(x));
+ assert(acc(x)); // ERROR: should fail
}
method s7() // ERROR: postcondition does not hold
- // requires acc(x);
- // ensures read2;
+ requires acc(x);
+ ensures read2;
{
- // fold rd(read2);
+ fold rd(read2);
}
// --- helper functions ---
diff --git a/Chalice/tests/permission-model/scaling.output.txt b/Chalice/tests/permission-model/scaling.output.txt
index d57ab458..2ba1640a 100644
--- a/Chalice/tests/permission-model/scaling.output.txt
+++ b/Chalice/tests/permission-model/scaling.output.txt
@@ -1,4 +1,16 @@
Verification of scaling.chalice using parameters=""
+ 20.5: Assertion might not hold. Insufficient fraction at 20.12 for Cell.x.
+ 23.3: The postcondition at 25.13 might not hold. Insufficient fraction at 25.13 for Cell.read1.
+ 37.5: Assertion might not hold. Insufficient fraction at 37.12 for Cell.x.
+ 40.3: The postcondition at 42.13 might not hold. Insufficient fraction at 42.13 for Cell.read1.
+ 52.5: Assertion might not hold. Insufficient fraction at 52.12 for Cell.x.
+ 61.5: Assertion might not hold. Insufficient fraction at 61.12 for Cell.x.
+ 64.3: The postcondition at 66.13 might not hold. Insufficient fraction at 66.13 for Cell.read2.
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+The program did not fully verify; the smoke warnings might be misleading if contradictions are introduced by failing proof attempts of the verification.
+ 15.3: The end of method s1 is unreachable.
+ 31.3: The end of method s3 is unreachable.
+ 55.3: The end of method s6 is unreachable.
+
+Boogie program verifier finished with 7 errors and 3 smoke test warnings
diff --git a/Chalice/tests/permission-model/sequences.output.txt b/Chalice/tests/permission-model/sequences.output.txt
index f557b8c7..7c295c9d 100644
--- a/Chalice/tests/permission-model/sequences.output.txt
+++ b/Chalice/tests/permission-model/sequences.output.txt
@@ -3,4 +3,4 @@ Verification of sequences.chalice using parameters=""
36.3: The postcondition at 41.13 might not hold. Insufficient permission at 41.13 for A.f
60.3: The postcondition at 65.13 might not hold. Insufficient permission at 65.13 for A.f
-Boogie program verifier finished with 2 errors and 0 smoke test warnings.
+Boogie program verifier finished with 2 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/FoldUnfoldExperiments.output.txt b/Chalice/tests/predicates/FoldUnfoldExperiments.output.txt
index 7239cf05..ba48d6f4 100644
--- a/Chalice/tests/predicates/FoldUnfoldExperiments.output.txt
+++ b/Chalice/tests/predicates/FoldUnfoldExperiments.output.txt
@@ -1,4 +1,4 @@
Verification of FoldUnfoldExperiments.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/LinkedList-various.chalice b/Chalice/tests/predicates/LinkedList-various.chalice
new file mode 100644
index 00000000..a888b647
--- /dev/null
+++ b/Chalice/tests/predicates/LinkedList-various.chalice
@@ -0,0 +1,176 @@
+class Node
+{
+ var v:int;
+ var n:Node;
+
+ predicate inv
+ { acc(v) && acc(n) && (n!=null ==> n.inv) }
+
+ function len():int
+ requires inv;
+ ensures result>0;
+ {
+ unfolding inv in (n==null) ? 1 : 1+n.len()
+ }
+
+ function get(i:int):int
+ requires inv && 0<=i && i<len();
+ {
+ unfolding inv in (i==0) ? v : n.get(i-1)
+ }
+
+ method addLast(x:int)
+ requires inv;
+ ensures inv;
+ ensures len()==old(len())+1 && get(old(len()))==x;
+ ensures (forall i:int :: 0<=i && i<old(len()) ==> get(i)==old(get(i)));
+ {
+ unfold inv;
+ if(n==null)
+ {
+ n:=new Node;
+ n.v:=x; n.n:=null;
+ fold n.inv;
+ }
+ else
+ {
+ call n.addLast(x);
+ }
+ fold inv;
+ }
+
+ method append(p:List)
+ requires inv && p!=null && p.inv;
+ ensures inv;
+ ensures len()==old(len()+p.len());
+ ensures (forall i in [0..old(len())] :: get(i)==old(get(i)));
+ ensures (forall i in [old(len())..len()] :: get(i)==old(p.get(i-len())));
+ {
+ unfold inv;
+ if(n==null)
+ {
+ unfold p.inv;
+ n:=p.c;
+ }
+ else
+ {
+ call n.append(p);
+ }
+ fold inv;
+ }
+
+ method remove(i:int)
+ requires inv && i>=0 && i<len()-1;
+ ensures inv;
+ ensures len()==old(len())-1;
+ ensures (forall j in [0..i+1] :: get(j)==old(get(j)));
+ ensures (forall j in [i+1..len()] :: get(j)==old(get(j+1)));
+ {
+ unfold inv;
+ if(i==0)
+ {
+ unfold n.inv;
+ n:=n.n;
+ }
+ else
+ {
+ call n.remove(i-1);
+ }
+ fold inv;
+ }
+}
+
+class List
+{
+ var c:Node;
+
+ predicate inv { acc(c) && (c!=null ==> c.inv) }
+
+ function len():int
+ requires inv;
+ ensures result>=0;
+ {
+ unfolding inv in (c==null) ? 0 : c.len()
+ }
+
+ function get(i:int):int
+ requires inv && 0<=i && i<len();
+ {
+ unfolding inv in c.get(i)
+ }
+
+ method addFirst(x:int)
+ requires inv;
+ ensures inv;
+ ensures len()==old(len())+1 && get(0)==x;
+ ensures (forall i:int :: 1<=i && i<len() ==> get(i)==old(get(i-1)));
+ {
+ var p:Node;
+
+ unfold inv;
+ p:=new Node; p.v:=x; p.n:=c; c:=p;
+ fold c.inv;
+ assert c.len()==old(len())+1
+ fold inv;
+ }
+
+ method addLast(x:int)
+ requires inv;
+ ensures inv;
+ ensures len()==old(len())+1 && get(old(len()))==x;
+ ensures (forall i:int :: 0<=i && i<old(len()) ==> get(i)==old(get(i)));
+ {
+ unfold inv;
+ if(c==null)
+ {
+ c:=new Node;
+ c.v:=x; c.n:=null;
+ fold c.inv;
+ }
+ else
+ {
+ call c.addLast(x);
+ }
+ fold inv;
+ }
+
+ method append(p:List)
+ requires inv && p!=null && p.inv;
+ ensures inv;
+ ensures len()==old(len()+p.len());
+ ensures (forall i in [0..old(len())] :: get(i)==old(get(i)));
+ ensures (forall i in [old(len())..len()] :: get(i)==old(p.get(i-len())));
+ {
+ unfold inv;
+ if(c==null)
+ {
+ unfold p.inv;
+ c:=p.c;
+ }
+ else
+ {
+ call c.append(p);
+ }
+ fold inv;
+ }
+
+ method remove(i:int)
+ requires inv && i>=0 && i<len();
+ ensures inv;
+ ensures len()==old(len())-1;
+ ensures (forall j in [0..i] :: get(j)==old(get(j)));
+ ensures (forall j in [i..len()] :: get(j)==old(get(j+1)));
+ {
+ unfold inv;
+ if(i==0)
+ {
+ unfold c.inv;
+ c:=c.n;
+ }
+ else
+ {
+ call c.remove(i-1);
+ }
+ fold inv;
+ }
+} \ No newline at end of file
diff --git a/Chalice/tests/predicates/LinkedList-various.output.txt b/Chalice/tests/predicates/LinkedList-various.output.txt
new file mode 100644
index 00000000..a8a90bb8
--- /dev/null
+++ b/Chalice/tests/predicates/LinkedList-various.output.txt
@@ -0,0 +1,4 @@
+Verification of LinkedList-various.chalice using parameters=""
+
+
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/aux-info.output.txt b/Chalice/tests/predicates/aux-info.output.txt
index ae84772b..3d873f60 100644
--- a/Chalice/tests/predicates/aux-info.output.txt
+++ b/Chalice/tests/predicates/aux-info.output.txt
@@ -1,4 +1,4 @@
Verification of aux-info.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/framing-fields.chalice b/Chalice/tests/predicates/framing-fields.chalice
index ce168f26..6cfd4607 100644
--- a/Chalice/tests/predicates/framing-fields.chalice
+++ b/Chalice/tests/predicates/framing-fields.chalice
@@ -11,9 +11,6 @@ class C
{
method M (x:List, y:List)
requires x!=null && y!=null && x!=y && x.valid && y.valid;
- requires unfolding x.valid in x.next!=y;
- requires unfolding y.valid in y.next!=x;
- // the two requirements above are needed, otherwise Chalice cannot prove that the two lists are disjoint
{
var i: int := unfolding x.valid in x.value;
var j: int := unfolding y.valid in y.value;
diff --git a/Chalice/tests/predicates/framing-fields.output.txt b/Chalice/tests/predicates/framing-fields.output.txt
index 3a7ea2ba..f1b426c6 100644
--- a/Chalice/tests/predicates/framing-fields.output.txt
+++ b/Chalice/tests/predicates/framing-fields.output.txt
@@ -1,5 +1,5 @@
Verification of framing-fields.chalice using parameters=""
- 22.5: Assertion might not hold. The expression at 22.12 might not evaluate to true.
+ 19.5: Assertion might not hold. The expression at 19.12 might not evaluate to true.
-Boogie program verifier finished with 1 errors and 0 smoke test warnings.
+Boogie program verifier finished with 1 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/framing-functions.output.txt b/Chalice/tests/predicates/framing-functions.output.txt
index 01bdd7bb..2a3426c9 100644
--- a/Chalice/tests/predicates/framing-functions.output.txt
+++ b/Chalice/tests/predicates/framing-functions.output.txt
@@ -2,4 +2,4 @@ Verification of framing-functions.chalice using parameters=""
23.5: Assertion might not hold. The expression at 23.12 might not evaluate to true.
-Boogie program verifier finished with 1 errors and 0 smoke test warnings.
+Boogie program verifier finished with 1 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/list-reverse-extra-unfold-fold.chalice b/Chalice/tests/predicates/list-reverse-extra-unfold-fold.chalice
new file mode 100644
index 00000000..8467ce4c
--- /dev/null
+++ b/Chalice/tests/predicates/list-reverse-extra-unfold-fold.chalice
@@ -0,0 +1,51 @@
+class Node {
+ var next : Node;
+ var val : int;
+
+ predicate list {
+ acc(next) && acc(val) && (next!=null ==> next.list)
+ }
+
+ function vals() : seq<int>
+ requires list
+ {
+ unfolding list in (next == null ? [val] : [val] ++ next.vals())
+ }
+
+ function reverse_vals() : seq<int>
+ requires list
+ {
+ unfolding list in (next == null ? [val] : next.reverse_vals() ++ [val])
+ }
+
+ method reverse_in_place() returns (r:Node)
+ requires list;
+ ensures r != null && r.list;
+ ensures r.vals() == old(this.reverse_vals());
+ {
+ var l : Node := this;
+ r := null;
+
+ while (l != null)
+ invariant l!=null ==> l.list;
+ invariant r!=null ==> r.list;
+ invariant old(this.reverse_vals()) == (l==null ? nil<int> : l.reverse_vals()) ++ (r==null ? nil<int> : r.vals());
+ {
+ var y: Node;
+ if (r != null) {
+ unfold r.list; fold r.list;
+ }
+ unfold l.list;
+ if (l.next != null) {
+ unfold l.next.list; fold l.next.list;
+ }
+
+
+ y := l.next;
+ l.next := r;
+ r := l;
+ fold r.list;
+ l := y;
+ }
+ }
+} \ No newline at end of file
diff --git a/Chalice/tests/predicates/list-reverse-extra-unfold-fold.output.txt b/Chalice/tests/predicates/list-reverse-extra-unfold-fold.output.txt
new file mode 100644
index 00000000..6d2967f5
--- /dev/null
+++ b/Chalice/tests/predicates/list-reverse-extra-unfold-fold.output.txt
@@ -0,0 +1,4 @@
+Verification of list-reverse-extra-unfold-fold.chalice using parameters=""
+
+
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/mutual-dependence.output.txt b/Chalice/tests/predicates/mutual-dependence.output.txt
index a35556a9..263084ac 100644
--- a/Chalice/tests/predicates/mutual-dependence.output.txt
+++ b/Chalice/tests/predicates/mutual-dependence.output.txt
@@ -2,4 +2,4 @@ Verification of mutual-dependence.chalice using parameters=""
16.5: Assertion might not hold. The expression at 16.12 might not evaluate to true.
-Boogie program verifier finished with 1 errors and 0 smoke test warnings.
+Boogie program verifier finished with 1 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/setset.output.txt b/Chalice/tests/predicates/setset.output.txt
index c20911f0..b2e963ee 100644
--- a/Chalice/tests/predicates/setset.output.txt
+++ b/Chalice/tests/predicates/setset.output.txt
@@ -5,4 +5,4 @@ Verification of setset.chalice using parameters=""
The program did not fully verify; the smoke warnings might be misleading if contradictions are introduced by failing proof attempts of the verification.
27.3: The end of method main is unreachable.
-Boogie program verifier finished with 1 errors and 1 smoke test warnings.
+Boogie program verifier finished with 1 errors and 1 smoke test warnings
diff --git a/Chalice/tests/predicates/test.chalice b/Chalice/tests/predicates/test.chalice
index 6c416671..9477caa6 100644
--- a/Chalice/tests/predicates/test.chalice
+++ b/Chalice/tests/predicates/test.chalice
@@ -30,9 +30,6 @@ class List
fork t:=skip();
// mask: value=0,p=100, secmask: -
assert unfolding P in value==old(value);
- // ERROR: Chalice currently cannot verify this example, as there is neither
- // primary nor secondary permission available to value directly before the
- // assertion
}
}
diff --git a/Chalice/tests/predicates/test.output.txt b/Chalice/tests/predicates/test.output.txt
index e05e1b4e..8b97e503 100644
--- a/Chalice/tests/predicates/test.output.txt
+++ b/Chalice/tests/predicates/test.output.txt
@@ -1,5 +1,4 @@
Verification of test.chalice using parameters=""
- 32.5: Assertion might not hold. The expression at 32.12 might not evaluate to true.
-Boogie program verifier finished with 1 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/test1.output.txt b/Chalice/tests/predicates/test1.output.txt
index 73be63ec..56888ecb 100644
--- a/Chalice/tests/predicates/test1.output.txt
+++ b/Chalice/tests/predicates/test1.output.txt
@@ -1,4 +1,4 @@
Verification of test1.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/test10.output.txt b/Chalice/tests/predicates/test10.output.txt
index d38b56a0..c043cbed 100644
--- a/Chalice/tests/predicates/test10.output.txt
+++ b/Chalice/tests/predicates/test10.output.txt
@@ -1,4 +1,4 @@
Verification of test10.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/test2.output.txt b/Chalice/tests/predicates/test2.output.txt
index d0bed944..780c15ef 100644
--- a/Chalice/tests/predicates/test2.output.txt
+++ b/Chalice/tests/predicates/test2.output.txt
@@ -1,4 +1,4 @@
Verification of test2.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/test3.output.txt b/Chalice/tests/predicates/test3.output.txt
index 7e4e49d6..2753e3f5 100644
--- a/Chalice/tests/predicates/test3.output.txt
+++ b/Chalice/tests/predicates/test3.output.txt
@@ -1,4 +1,4 @@
Verification of test3.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/test4.output.txt b/Chalice/tests/predicates/test4.output.txt
index 5268bec7..08a565c8 100644
--- a/Chalice/tests/predicates/test4.output.txt
+++ b/Chalice/tests/predicates/test4.output.txt
@@ -2,4 +2,4 @@ Verification of test4.chalice using parameters=""
54.2: Assertion might not hold. The expression at 54.9 might not evaluate to true.
-Boogie program verifier finished with 1 errors and 0 smoke test warnings.
+Boogie program verifier finished with 1 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/test7.output.txt b/Chalice/tests/predicates/test7.output.txt
index 46ac796c..e66a1d75 100644
--- a/Chalice/tests/predicates/test7.output.txt
+++ b/Chalice/tests/predicates/test7.output.txt
@@ -13,4 +13,4 @@ The program did not fully verify; the smoke warnings might be misleading if cont
62.3: The end of method uf0 is unreachable.
86.3: The end of method uf3 is unreachable.
-Boogie program verifier finished with 7 errors and 3 smoke test warnings.
+Boogie program verifier finished with 7 errors and 3 smoke test warnings
diff --git a/Chalice/tests/predicates/test8.output.txt b/Chalice/tests/predicates/test8.output.txt
index 881b2ef0..567d2894 100644
--- a/Chalice/tests/predicates/test8.output.txt
+++ b/Chalice/tests/predicates/test8.output.txt
@@ -1,4 +1,4 @@
Verification of test8.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/predicates/unfolding.chalice b/Chalice/tests/predicates/unfolding.chalice
index f01b237d..6b276a04 100644
--- a/Chalice/tests/predicates/unfolding.chalice
+++ b/Chalice/tests/predicates/unfolding.chalice
@@ -14,6 +14,7 @@ class Cell {
method test2()
requires p
+ ensures p
{
var tmp: int := unfolding p in value;
var tmp2: int := unfolding p in value;
diff --git a/Chalice/tests/predicates/unfolding.output.txt b/Chalice/tests/predicates/unfolding.output.txt
index 4a1ebbde..7ff49106 100644
--- a/Chalice/tests/predicates/unfolding.output.txt
+++ b/Chalice/tests/predicates/unfolding.output.txt
@@ -2,4 +2,4 @@ Verification of unfolding.chalice using parameters=""
12.5: Assertion might not hold. The expression at 12.12 might not evaluate to true.
-Boogie program verifier finished with 1 errors and 0 smoke test warnings.
+Boogie program verifier finished with 1 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/internal-bug-1.output.txt b/Chalice/tests/regressions/internal-bug-1.output.txt
index ea14d3e3..7685b77a 100644
--- a/Chalice/tests/regressions/internal-bug-1.output.txt
+++ b/Chalice/tests/regressions/internal-bug-1.output.txt
@@ -1,4 +1,4 @@
Verification of internal-bug-1.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/internal-bug-2.output.txt b/Chalice/tests/regressions/internal-bug-2.output.txt
index 3b763659..8724af64 100644
--- a/Chalice/tests/regressions/internal-bug-2.output.txt
+++ b/Chalice/tests/regressions/internal-bug-2.output.txt
@@ -5,4 +5,4 @@ Verification of internal-bug-2.chalice using parameters=""
The program did not fully verify; the smoke warnings might be misleading if contradictions are introduced by failing proof attempts of the verification.
6.5: The end of method koko is unreachable.
-Boogie program verifier finished with 1 errors and 1 smoke test warnings.
+Boogie program verifier finished with 1 errors and 1 smoke test warnings
diff --git a/Chalice/tests/regressions/internal-bug-4.chalice b/Chalice/tests/regressions/internal-bug-4.chalice
new file mode 100644
index 00000000..af850d49
--- /dev/null
+++ b/Chalice/tests/regressions/internal-bug-4.chalice
@@ -0,0 +1,17 @@
+class C
+{
+ var f: int;
+ predicate valid { acc(f) }
+
+ function foo1(): int
+ ensures valid;
+ { 1 }
+
+ function foo2(): int
+ ensures acc(f);
+ { 1 }
+
+ function foo3(): int
+ ensures rd(f);
+ { 1 }
+}
diff --git a/Chalice/tests/regressions/internal-bug-4.output.txt b/Chalice/tests/regressions/internal-bug-4.output.txt
new file mode 100644
index 00000000..a985df28
--- /dev/null
+++ b/Chalice/tests/regressions/internal-bug-4.output.txt
@@ -0,0 +1,6 @@
+Verification of internal-bug-4.chalice using parameters=""
+
+The program did not typecheck.
+7.3: the postcondition of functions cannot contain accessibility predicates (permissions are returned automatically)
+11.3: the postcondition of functions cannot contain accessibility predicates (permissions are returned automatically)
+15.3: the postcondition of functions cannot contain accessibility predicates (permissions are returned automatically)
diff --git a/Chalice/tests/regressions/internal-bug-5.chalice b/Chalice/tests/regressions/internal-bug-5.chalice
new file mode 100644
index 00000000..35dfcb88
--- /dev/null
+++ b/Chalice/tests/regressions/internal-bug-5.chalice
@@ -0,0 +1,38 @@
+class Cell {
+ var x: int;
+ var b: bool;
+
+ predicate valid {
+ acc(this.b) && (this.b ==> acc(this.x,50))
+ }
+
+ method m()
+ requires this.valid && (unfolding valid in this.b) && acc(this.mu) && waitlevel << mu
+ {
+ acquire this;
+
+ var c := (unfolding valid in this.x);
+ release this;
+ acquire this;
+ assert c == this.x;
+ call n();
+ c := (unfolding valid in this.x);
+ release this;
+ acquire this;
+ // ERROR: this is not supposed to verify (it did in previous versions of Chalice)
+ assert c == this.x;
+ release this;
+ }
+
+ method n()
+ requires this.valid
+ ensures this.valid
+ {
+ unfold this.valid;
+ this.b := false;
+ fold this.valid;
+ }
+
+ invariant acc(this.x,50)
+}
+
diff --git a/Chalice/tests/regressions/internal-bug-5.output.txt b/Chalice/tests/regressions/internal-bug-5.output.txt
new file mode 100644
index 00000000..3b6cc316
--- /dev/null
+++ b/Chalice/tests/regressions/internal-bug-5.output.txt
@@ -0,0 +1,5 @@
+Verification of internal-bug-5.chalice using parameters=""
+
+ 23.5: Assertion might not hold. The expression at 23.12 might not evaluate to true.
+
+Boogie program verifier finished with 1 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/internal-bug-6.chalice b/Chalice/tests/regressions/internal-bug-6.chalice
new file mode 100644
index 00000000..b02c1a65
--- /dev/null
+++ b/Chalice/tests/regressions/internal-bug-6.chalice
@@ -0,0 +1,10 @@
+class Cell {
+
+ function foo(): Cell
+ { this }
+
+ method m(b: bool)
+ {
+ var c: Cell := b ? null : foo()
+ }
+}
diff --git a/Chalice/tests/regressions/internal-bug-6.output.txt b/Chalice/tests/regressions/internal-bug-6.output.txt
new file mode 100644
index 00000000..5b7560cd
--- /dev/null
+++ b/Chalice/tests/regressions/internal-bug-6.output.txt
@@ -0,0 +1,4 @@
+Verification of internal-bug-6.chalice using parameters=""
+
+
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/internal-bug-7.chalice b/Chalice/tests/regressions/internal-bug-7.chalice
new file mode 100644
index 00000000..9f7d474d
--- /dev/null
+++ b/Chalice/tests/regressions/internal-bug-7.chalice
@@ -0,0 +1,26 @@
+class Node {
+ var n: Node
+
+ predicate P { acc(n) && (n != null ==> acc(n.P)) }
+
+ function length(): int
+ requires rd(P)
+ ensures result >= 1
+ { unfolding rd(P) in 1 + (n == null ? 0 : n.length()) }
+
+}
+
+class Test {
+ method test(node: Node)
+ requires node != null
+ requires acc(node.P)
+ {
+ assert node.length() >= 1
+ assert (unfolding rd(node.P) in node.n == null) ==> (node.length() == 1) /* Holds in Chalice and Syxc */
+ //assert (unfolding rd(node.P) in node.n != null) ==> (unfolding rd(node.P) in node.n.length() >= 1) /* Holds in Chalice and Syxc */
+ assert (unfolding rd(node.P) in node.n != null) ==> (node.length() > 1) /* Holds in Chalice and Syxc */
+ assert (node.length() == 1) ==> (unfolding rd(node.P) in node.n == null) /* Fails in Chalice and Syxc */
+ assert (node.length() == 1) <==> (unfolding rd(node.P) in node.n == null)
+ // assert n.length() > 1 <==> unfolding rd(n.P) in n.n != null /* Fails in Chalice and Syxc */
+ }
+} \ No newline at end of file
diff --git a/Chalice/tests/regressions/internal-bug-7.output.txt b/Chalice/tests/regressions/internal-bug-7.output.txt
new file mode 100644
index 00000000..78ae95fd
--- /dev/null
+++ b/Chalice/tests/regressions/internal-bug-7.output.txt
@@ -0,0 +1,4 @@
+Verification of internal-bug-7.chalice using parameters=""
+
+
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-10189.chalice b/Chalice/tests/regressions/workitem-10189.chalice
new file mode 100644
index 00000000..b37b83f2
--- /dev/null
+++ b/Chalice/tests/regressions/workitem-10189.chalice
@@ -0,0 +1,23 @@
+class Node {
+ var v: int
+ var next: Node
+
+ predicate V {
+ acc(v)
+ && acc(next)
+ && (next != null ==> next.V)
+ }
+
+ unlimited function length(): int
+ requires rd(V)
+ { 1 + unfolding rd(V) in next == null ? 0 : next.length() }
+
+ unlimited function at(i: int): int
+ requires rd(V)
+ requires i >= 0
+ requires i < length() // XXXX
+ {
+ unfolding rd(V) in i == 0 ? v : next.at(i - 1)
+ // Precondition at XXX might not hold
+ }
+} \ No newline at end of file
diff --git a/Chalice/tests/regressions/workitem-10189.output.txt b/Chalice/tests/regressions/workitem-10189.output.txt
new file mode 100644
index 00000000..96f05468
--- /dev/null
+++ b/Chalice/tests/regressions/workitem-10189.output.txt
@@ -0,0 +1,4 @@
+Verification of workitem-10189.chalice using parameters=""
+
+
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-10192.output.txt b/Chalice/tests/regressions/workitem-10192.output.txt
index 1f5fbeec..f2a5b539 100644
--- a/Chalice/tests/regressions/workitem-10192.output.txt
+++ b/Chalice/tests/regressions/workitem-10192.output.txt
@@ -1,4 +1,4 @@
Verification of workitem-10192.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-10194.output.txt b/Chalice/tests/regressions/workitem-10194.output.txt
index 580a8068..23114b0a 100644
--- a/Chalice/tests/regressions/workitem-10194.output.txt
+++ b/Chalice/tests/regressions/workitem-10194.output.txt
@@ -3,4 +3,4 @@ Verification of workitem-10194.chalice using parameters=""
20.35: Location might not be readable.
35.3: Assertion might not hold. The expression at 35.10 might not evaluate to true.
-Boogie program verifier finished with 2 errors and 0 smoke test warnings.
+Boogie program verifier finished with 2 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-10195.output.txt b/Chalice/tests/regressions/workitem-10195.output.txt
index 0636df17..6e8b3556 100644
--- a/Chalice/tests/regressions/workitem-10195.output.txt
+++ b/Chalice/tests/regressions/workitem-10195.output.txt
@@ -9,4 +9,4 @@ The program did not fully verify; the smoke warnings might be misleading if cont
19.9: Precondition of method succeeds2 is equivalent to false.
27.9: Precondition of method fails2 is equivalent to false.
-Boogie program verifier finished with 2 errors and 4 smoke test warnings.
+Boogie program verifier finished with 2 errors and 4 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-10196.output.txt b/Chalice/tests/regressions/workitem-10196.output.txt
index 013880cc..26199999 100644
--- a/Chalice/tests/regressions/workitem-10196.output.txt
+++ b/Chalice/tests/regressions/workitem-10196.output.txt
@@ -1,4 +1,4 @@
Verification of workitem-10196.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-10197.output.txt b/Chalice/tests/regressions/workitem-10197.output.txt
index 9cc1319a..c83bbfe0 100644
--- a/Chalice/tests/regressions/workitem-10197.output.txt
+++ b/Chalice/tests/regressions/workitem-10197.output.txt
@@ -1,4 +1,4 @@
Verification of workitem-10197.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-10198.output.txt b/Chalice/tests/regressions/workitem-10198.output.txt
index 8e421059..c3b59307 100644
--- a/Chalice/tests/regressions/workitem-10198.output.txt
+++ b/Chalice/tests/regressions/workitem-10198.output.txt
@@ -2,4 +2,4 @@ Verification of workitem-10198.chalice using parameters=""
12.2: Method might lock/unlock more than allowed.
-Boogie program verifier finished with 1 errors and 0 smoke test warnings.
+Boogie program verifier finished with 1 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-10199.output.txt b/Chalice/tests/regressions/workitem-10199.output.txt
index 4fb873e7..660fd6ae 100644
--- a/Chalice/tests/regressions/workitem-10199.output.txt
+++ b/Chalice/tests/regressions/workitem-10199.output.txt
@@ -1,4 +1,4 @@
Verification of workitem-10199.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-10200.output.txt b/Chalice/tests/regressions/workitem-10200.output.txt
index cac4bb62..90d5b467 100644
--- a/Chalice/tests/regressions/workitem-10200.output.txt
+++ b/Chalice/tests/regressions/workitem-10200.output.txt
@@ -2,4 +2,4 @@ Verification of workitem-10200.chalice using parameters=""
7.15: The heap of the callee might not be strictly smaller than the heap of the caller.
-Boogie program verifier finished with 1 errors and 0 smoke test warnings.
+Boogie program verifier finished with 1 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-10208.chalice b/Chalice/tests/regressions/workitem-10208.chalice
new file mode 100644
index 00000000..ae1a7d89
--- /dev/null
+++ b/Chalice/tests/regressions/workitem-10208.chalice
@@ -0,0 +1,41 @@
+class Test {
+ var f1: int;
+ var f2: int;
+
+ predicate valid {
+ acc(f1) && acc(f2) && f1 == f2
+ }
+
+ method test()
+ requires valid
+ {
+ unfold valid
+ f1 := 2
+ f2 := 2
+ fold valid
+
+ /* --- not strictly necessary */
+ unfold valid
+ assert f1 == 2
+ fold valid
+ /* --- */
+
+ call test2()
+
+ unfold valid
+ assert f1 == 2 // BUG: this should not verify (1)
+ assert false // BUG: this should not verify (2)
+ }
+
+ method test2()
+ requires valid
+ ensures valid
+ ensures unfolding valid in f1 == 1 // line (1) above verifies also without this postcondition
+ {
+ unfold valid
+ f1 := 1
+ f2 := 1
+ fold valid
+ }
+
+}
diff --git a/Chalice/tests/regressions/workitem-10208.output.txt b/Chalice/tests/regressions/workitem-10208.output.txt
new file mode 100644
index 00000000..0666393a
--- /dev/null
+++ b/Chalice/tests/regressions/workitem-10208.output.txt
@@ -0,0 +1,8 @@
+Verification of workitem-10208.chalice using parameters=""
+
+ 26.5: Assertion might not hold. The expression at 26.12 might not evaluate to true.
+
+The program did not fully verify; the smoke warnings might be misleading if contradictions are introduced by failing proof attempts of the verification.
+ 9.3: The end of method test is unreachable.
+
+Boogie program verifier finished with 1 errors and 1 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-10221.chalice b/Chalice/tests/regressions/workitem-10221.chalice
new file mode 100644
index 00000000..2a8ae723
--- /dev/null
+++ b/Chalice/tests/regressions/workitem-10221.chalice
@@ -0,0 +1,158 @@
+// In this example, additional unfold/fold pairs make the verification of the last three methods fail.
+
+class Node {
+ var next : Node;
+ var val : int;
+
+ predicate list {
+ acc(next) && acc(val) && (next!=null ==> next.list)
+ }
+
+ function vals() : seq<int>
+ requires list
+ {
+ unfolding list in (next == null ? [val] : [val] ++ next.vals())
+ }
+
+ function reverse_vals() : seq<int>
+ requires list
+ {
+ unfolding list in (next == null ? [val] : next.reverse_vals() ++ [val])
+ }
+
+ method reverse_in_place() returns (r:Node)
+ requires list;
+ ensures true;
+ {
+ var l : Node := this;
+ r := null;
+
+ var rev : seq<int> := this.reverse_vals();
+
+ while (l != null)
+ invariant l!=null ==> l.list;
+ invariant r!=null ==> r.list;
+ invariant rev == (l==null ? nil<int> : l.reverse_vals()) ++ (r==null ? nil<int> : r.vals());
+ {
+ var y: Node;
+// if (r != null) {
+// unfold r.list; fold r.list;
+// }
+ unfold l.list;
+// if (l.next != null) {
+// unfold l.next.list; fold l.next.list;
+// }
+
+ y := l.next;
+ l.next := r;
+ r := l;
+ fold r.list;
+ l := y;
+ }
+ assert r.vals() == rev; // should be the post-condition
+ }
+
+
+ method reverse_in_place_01() returns (r:Node)
+ requires list;
+ ensures true;
+ {
+ var l : Node := this;
+ r := null;
+
+ var rev : seq<int> := this.reverse_vals();
+
+ while (l != null)
+ invariant l!=null ==> l.list;
+ invariant r!=null ==> r.list;
+ invariant rev == (l==null ? nil<int> : l.reverse_vals()) ++ (r==null ? nil<int> : r.vals());
+ {
+ var y: Node;
+// if (r != null) {
+// unfold r.list; fold r.list;
+// }
+ unfold l.list;
+ if (l.next != null) {
+ unfold l.next.list; fold l.next.list;
+ }
+
+ y := l.next;
+ l.next := r;
+ r := l;
+ fold r.list;
+ l := y;
+ }
+ assert r.vals() == rev; // should be the post-condition
+ }
+
+
+
+ method reverse_in_place_10() returns (r:Node)
+ requires list;
+ ensures true;
+ {
+ var l : Node := this;
+ r := null;
+
+ var rev : seq<int> := this.reverse_vals();
+
+ while (l != null)
+ invariant l!=null ==> l.list;
+ invariant r!=null ==> r.list;
+ invariant rev == (l==null ? nil<int> : l.reverse_vals()) ++ (r==null ? nil<int> : r.vals());
+ {
+ var y: Node;
+ if (r != null) {
+ unfold r.list; fold r.list;
+ }
+ unfold l.list;
+// if (l.next != null) {
+// unfold l.next.list; fold l.next.list;
+// }
+
+ y := l.next;
+ l.next := r;
+ r := l;
+ fold r.list;
+ l := y;
+ }
+ assert r.vals() == rev; // should be the post-condition
+ }
+
+
+
+
+ method reverse_in_place_11() returns (r:Node)
+ requires list;
+ ensures true;
+ {
+ var l : Node := this;
+ r := null;
+
+ var rev : seq<int> := this.reverse_vals();
+
+ while (l != null)
+ invariant l!=null ==> l.list;
+ invariant r!=null ==> r.list;
+ invariant rev == (l==null ? nil<int> : l.reverse_vals()) ++ (r==null ? nil<int> : r.vals());
+ {
+ var y: Node;
+ if (r != null) {
+ unfold r.list; fold r.list;
+ }
+ unfold l.list;
+ if (l.next != null) {
+ unfold l.next.list; fold l.next.list;
+ }
+
+ y := l.next;
+ l.next := r;
+ r := l;
+ fold r.list;
+ l := y;
+ }
+ assert r.vals() == rev; // should be the post-condition
+ }
+
+
+} \ No newline at end of file
diff --git a/Chalice/tests/regressions/workitem-10221.output.txt b/Chalice/tests/regressions/workitem-10221.output.txt
new file mode 100644
index 00000000..e209c3c1
--- /dev/null
+++ b/Chalice/tests/regressions/workitem-10221.output.txt
@@ -0,0 +1,4 @@
+Verification of workitem-10221.chalice using parameters=""
+
+
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-10223.output.txt b/Chalice/tests/regressions/workitem-10223.output.txt
index f4bfd78d..b65fbc0c 100644
--- a/Chalice/tests/regressions/workitem-10223.output.txt
+++ b/Chalice/tests/regressions/workitem-10223.output.txt
@@ -1,4 +1,4 @@
Verification of workitem-10223.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-8234.output.txt b/Chalice/tests/regressions/workitem-8234.output.txt
index 8d13e17a..14175fd2 100644
--- a/Chalice/tests/regressions/workitem-8234.output.txt
+++ b/Chalice/tests/regressions/workitem-8234.output.txt
@@ -1,4 +1,4 @@
Verification of workitem-8234.chalice using parameters=""
-Boogie program verifier finished with 0 errors and 0 smoke test warnings.
+Boogie program verifier finished with 0 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-8236.output.txt b/Chalice/tests/regressions/workitem-8236.output.txt
index 30b42ab1..6f1994d3 100644
--- a/Chalice/tests/regressions/workitem-8236.output.txt
+++ b/Chalice/tests/regressions/workitem-8236.output.txt
@@ -2,4 +2,4 @@ Verification of workitem-8236.chalice using parameters=""
3.2: Method might lock/unlock more than allowed.
-Boogie program verifier finished with 1 errors and 0 smoke test warnings.
+Boogie program verifier finished with 1 errors and 0 smoke test warnings
diff --git a/Chalice/tests/regressions/workitem-9978.output.txt b/Chalice/tests/regressions/workitem-9978.output.txt
index 0e557a3b..e6086625 100644
--- a/Chalice/tests/regressions/workitem-9978.output.txt
+++ b/Chalice/tests/regressions/workitem-9978.output.txt
@@ -3,4 +3,4 @@ Verification of workitem-9978.chalice using parameters=""
4.5: The statements after the while-loop are unreachable.
-Boogie program verifier finished with 0 errors and 1 smoke test warnings.
+Boogie program verifier finished with 0 errors and 1 smoke test warnings
diff --git a/Chalice/tests/test-scripts/getboogieoutput.bat b/Chalice/tests/test-scripts/getboogieoutput.bat
index f7b729fe..76af1fcf 100644
--- a/Chalice/tests/test-scripts/getboogieoutput.bat
+++ b/Chalice/tests/test-scripts/getboogieoutput.bat
@@ -25,7 +25,7 @@ if "!key!"=="!str!" (
echo Verification of %1.chalice using parameters="%chaliceparameters%" > %output%
echo.>> %output%
-call %chalice% "%1.chalice" -smoke %chaliceparameters% %2 %3 %4 %5 %6 %7 >> %output% 2>&1
+call %chalice% "%1.chalice" -smoke -time:0 %chaliceparameters% %2 %3 %4 %5 %6 %7 >> %output% 2>&1
set o=%~dp1%out.bpl
if exist "%o%" copy "%o%" "%1.bpl">nul
diff --git a/Chalice/tests/test-scripts/reg_test.bat b/Chalice/tests/test-scripts/reg_test.bat
index c6ab8424..54549afc 100644
--- a/Chalice/tests/test-scripts/reg_test.bat
+++ b/Chalice/tests/test-scripts/reg_test.bat
@@ -35,18 +35,20 @@ if "!key!"=="!str!" (
set output=output.txt
echo Verification of %1.chalice using parameters="%chaliceparameters%" > %output%
echo.>> %output%
-call %chalice% "%1.chalice" -smoke %chaliceparameters% %2 %3 %4 %5 %6 %7 >> %output% 2>&1
+call %chalice% "%1.chalice" -smoke -time:3 %chaliceparameters% %2 %3 %4 %5 %6 %7 1>> %output% 2> time.log
+set /p extime= < time.log
+del time.log
fc "%1.output.txt" output.txt > nul
if not errorlevel 1 goto passTest
goto failTest
:passTest
-echo OK: %1.chalice
+echo OK: %1.chalice (%extime% seconds)
goto end
:failTest
-echo FAIL: %1.chalice
+echo FAIL: %1.chalice (%extime% seconds)
if %nodiff%==0 (
call %diff% "%1.output.txt" output.txt
)
diff --git a/Chalice/tests/test-scripts/test.bat b/Chalice/tests/test-scripts/test.bat
index 30e135bd..8572dc6b 100644
--- a/Chalice/tests/test-scripts/test.bat
+++ b/Chalice/tests/test-scripts/test.bat
@@ -27,7 +27,7 @@ if "!key!"=="!str!" (
set output=output.txt
echo Verification of %1.chalice using parameters="%chaliceparameters%" > %output%
echo.>> %output%
-call %chalice% "%1.chalice" -smoke %chaliceparameters% %2 %3 %4 %5 %6 %7 >> %output% 2>&1
+call %chalice% "%1.chalice" -smoke -time:0 %chaliceparameters% %2 %3 %4 %5 %6 %7 >> %output% 2>&1
type %output%
exit /B 0
diff --git a/Source/AbsInt/AbsInt.csproj b/Source/AbsInt/AbsInt.csproj
index 9ccd0ffe..7e421eb1 100644
--- a/Source/AbsInt/AbsInt.csproj
+++ b/Source/AbsInt/AbsInt.csproj
@@ -212,20 +212,13 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
- <Compile Include="AbstractInterpretation.cs" />
- <Compile Include="ExprFactories.cs" />
<Compile Include="IntervalDomain.cs" />
- <Compile Include="LoopInvariantsOnDemand.cs" />
<Compile Include="TrivialDomain.cs" />
<Compile Include="NativeLattice.cs" />
<Compile Include="Traverse.cs" />
<Compile Include="..\version.cs" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
<ProjectReference Include="..\Basetypes\Basetypes.csproj">
<Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
<Name>Basetypes</Name>
diff --git a/Source/AbsInt/AbstractInterpretation.cs b/Source/AbsInt/AbstractInterpretation.cs
deleted file mode 100644
index d69c624a..00000000
--- a/Source/AbsInt/AbstractInterpretation.cs
+++ /dev/null
@@ -1,916 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-namespace Microsoft.Boogie.AbstractInterpretation {
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Diagnostics.Contracts;
- using Microsoft.Boogie;
- using System.Linq;
- using AI = Microsoft.AbstractInterpretationFramework;
-
-
- /// <summary>
- /// Defines invariant propagation methods over ASTs for an abstract interpretation policy.
- /// </summary>
- public class AbstractionEngine {
- private AI.Lattice lattice;
- private Queue<ProcedureWorkItem> procWorkItems; //PM: changed to generic queue
- private Queue/*<CallSite>*/ callReturnWorkItems;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(lattice != null);
- Contract.Invariant(procWorkItems != null);
- Contract.Invariant(callReturnWorkItems != null);
- }
-
-
- private class ProcedureWorkItem {
- [Rep] // KRML: this doesn't seem like the right designation to me; but I'm not sure what is
- public Procedure Proc;
-
- public int Index; // pre state is Impl.Summary[Index]
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Proc != null);
- Contract.Invariant(0 <= Index && Index < Proc.Summary.Count);
- Contract.Invariant(log != null);
- }
-
- public ProcedureWorkItem([Captured] Procedure p, AI.Lattice.Element v, AI.Lattice lattice) {
- Contract.Requires(p != null);
- Contract.Requires(v != null);
- Contract.Requires(lattice != null);
-
- Contract.Ensures(p == Proc);
- this.Proc = p;
- p.Summary.Add(new ProcedureSummaryEntry(lattice, v));
- this.Index = p.Summary.Count - 1;
- // KRML: axioms are now in place: assume 0 <= Index && Index < Proc.Summary.Count; //PM: Should not be necessary once axioms for pure methods are there
- }
- }
-
- private readonly static AI.Logger log = new AI.Logger("Engine");
-
-
- public AbstractionEngine(AI.Lattice lattice) {
- Contract.Requires(lattice != null);
- Contract.Assume(cce.IsExposable(log)); //PM: One would need static class invariants to prove this property
- cce.BeginExpose(log);
- log.Enabled = AI.Lattice.LogSwitch;
- cce.EndExpose();
- this.lattice = lattice;
- this.procWorkItems = new Queue<ProcedureWorkItem>();
- this.callReturnWorkItems = new Queue();
- }
-
- public static Dictionary<Procedure, Implementation[]> ComputeProcImplMap(Program program) {
- Contract.Requires(program != null);
- // Since implementations call procedures (impl. signatures)
- // rather than directly calling other implementations, we first
- // need to compute which implementations implement which
- // procedures and remember which implementations call which
- // procedures.
-
- return program
- .TopLevelDeclarations
- .Where(d => d is Implementation).Select(i => (Implementation)i)
- .GroupBy(i => i.Proc).Select(g => g.ToArray()).ToDictionary(a => a[0].Proc);
-
- }
-
- public AI.Lattice.Element ApplyProcedureSummary(CallCmd call, Implementation caller, AI.Lattice.Element knownAtCallSite, CallSite callSite) {
- Contract.Requires(call.Proc != null);
- Contract.Requires(call != null);
- Contract.Requires(caller != null);
- Contract.Requires(knownAtCallSite != null);
- Contract.Requires(callSite != null);
-
- Contract.Ensures(Contract.Result<AI.Lattice.Element>() != null);
- Procedure proc = call.Proc;//Precondition required that call.Proc !=null, therefore no assert necessarry.
-
- // NOTE: Here, we count on the fact that an implementation's variables
- // are distinct from an implementation's procedure's variables. So, even for
- // a recursive implementation, we're free to use the implementation's
- // procedure's input parameters as though they were temporary local variables.
- //
- // Hence, in the program
- // procedure Foo (i:int); implementation Foo (i':int) { ...call Foo(i'+1)... }
- // we can treat the recursive call as
- // i:=i'+1; call Foo(i);
- // where the notation i' means a variable with the same (string) name as i,
- // but a different identity.
-
- AI.Lattice.Element relevantToCall = knownAtCallSite; //Precondition of the method implies that this can never be null, therefore no need for an assert.
- for (int i = 0; i < proc.InParams.Length; i++) {
- // "Assign" the actual expressions to the corresponding formal variables.
- Contract.Assume(proc.InParams[i] != null); //PM: this can be fixed once VariableSeq is replaced by List<Variable!>;
- Contract.Assume(call.Ins[i] != null); //PM: this can be fixed once VariableSeq is replaced by List<Variable!>;
- Expr equality = Expr.Eq(Expr.Ident(cce.NonNull(proc.InParams[i])), cce.NonNull(call.Ins[i]));
- relevantToCall = lattice.Constrain(relevantToCall, equality.IExpr);
- }
- foreach (Variable var in caller.LocVars) {
- Contract.Assert(var != null);
- relevantToCall = this.lattice.Eliminate(relevantToCall, var);
- }
-
- ProcedureSummary summary = proc.Summary;
- Contract.Assert(summary != null);
- ProcedureSummaryEntry applicableEntry = null;
-
- for (int i = 0; i < summary.Count; i++) {
- ProcedureSummaryEntry current = cce.NonNull(summary[i]);
-
- if (lattice.Equivalent(current.OnEntry, relevantToCall)) {
- applicableEntry = current;
- break;
- }
- }
-
- // Not found in current map, so add new entry.
- if (applicableEntry == null) {
- ProcedureWorkItem newWorkItem = new ProcedureWorkItem(proc, relevantToCall, lattice);
- Contract.Assert(newWorkItem != null);
- this.procWorkItems.Enqueue(newWorkItem);
- applicableEntry = cce.NonNull(proc.Summary[newWorkItem.Index]);
- }
- applicableEntry.ReturnPoints.Add(callSite);
-
-
- AI.Lattice.Element atReturn = applicableEntry.OnExit;
-
- for (int i = 0; i < call.Outs.Count; i++) {
- atReturn = this.lattice.Rename(atReturn, cce.NonNull(call.Proc.OutParams[i]), cce.NonNull(cce.NonNull(call.Outs[i]).Decl));
- knownAtCallSite = this.lattice.Eliminate(knownAtCallSite, cce.NonNull(cce.NonNull(call.Outs[i]).Decl));
- }
-
- return this.lattice.Meet(atReturn, knownAtCallSite);
- }
-
- /// <summary>
- /// Compute the invariants for the program using the underlying abstract domain
- /// </summary>
- public void ComputeProgramInvariants(Program program) {
- Contract.Requires(program != null);
-
- Dictionary<Procedure, Implementation[]> procedureImplementations = ComputeProcImplMap(program);
- //the line above, ergo there is no need for
- //an assert after this statement to maintain
- //the non-null type.
- AI.Lattice.Element initialElement = this.lattice.Top;
- Contract.Assert(initialElement != null);
- // Gather all the axioms to create the initial lattice element
- // Differently stated, it is the \alpha from axioms (i.e. first order formulae) to the underlyng abstract domain
-
- foreach (Declaration decl in program.TopLevelDeclarations) {
- Axiom ax = decl as Axiom;
- if (ax != null) {
- initialElement = this.lattice.Constrain(initialElement, ax.Expr.IExpr);
- }
- }
-
- // propagate over all procedures...
- foreach (Declaration decl in program.TopLevelDeclarations) {
- Procedure proc = decl as Procedure;
- if (proc != null) {
- this.procWorkItems.Enqueue(new ProcedureWorkItem(proc, initialElement, this.lattice));
- }
- }
-
- // analyze all the procedures...
- while (this.procWorkItems.Count + this.callReturnWorkItems.Count > 0) {
- while (this.procWorkItems.Count > 0) {
- ProcedureWorkItem workItem = this.procWorkItems.Dequeue();
-
- ProcedureSummaryEntry summaryEntry = cce.NonNull(workItem.Proc.Summary[workItem.Index]);
- if (!procedureImplementations.ContainsKey(workItem.Proc)) {
- // This procedure has no given implementations. We therefore treat the procedure
- // according to its specification only.
-
- if (!CommandLineOptions.Clo.IntraproceduralInfer) {
- AI.Lattice.Element post = summaryEntry.OnEntry;
- // BUGBUG. Here, we should process "post" according to the requires, modifies, ensures
- // specification of the procedure, including any OLD expressions in the postcondition.
- AI.Lattice.Element atReturn = post;
-
- if (!this.lattice.LowerThan(atReturn, summaryEntry.OnExit)) {
- // If the results of this analysis are strictly worse than
- // what we previous knew for the same input assumptions,
- // update the summary and re-do the call sites.
-
- summaryEntry.OnExit = this.lattice.Join(summaryEntry.OnExit, atReturn);
-
- foreach (CallSite callSite in summaryEntry.ReturnPoints) {
- this.callReturnWorkItems.Enqueue(callSite);
- }
- }
- }
- } else {
- // There are implementations, so do inference based on those implementations
-
- if (!CommandLineOptions.Clo.IntraproceduralInfer) {
- summaryEntry.OnExit = lattice.Bottom;
- }
-
- // For each implementation in the procedure...
- foreach (Implementation impl in cce.NonNull(procedureImplementations[workItem.Proc])) {
- // process each procedure implementation by recursively processing the first (entry) block...
- cce.NonNull(impl.Blocks[0]).Lattice = lattice;
- ComputeBlockInvariants(impl, cce.NonNull(impl.Blocks[0]), summaryEntry.OnEntry, summaryEntry);
- AdjustProcedureSummary(impl, summaryEntry);
- }
- }
- }
-
-
- while (this.callReturnWorkItems.Count > 0) {
- CallSite callSite = cce.NonNull((CallSite)this.callReturnWorkItems.Dequeue());
-
- PropagateStartingAtStatement(callSite.Impl, callSite.Block, callSite.Statement, callSite.KnownBeforeCall, callSite.SummaryEntry);
- AdjustProcedureSummary(callSite.Impl, callSite.SummaryEntry);
- }
-
- } // both queues
-
- }
-
- void AdjustProcedureSummary(Implementation impl, ProcedureSummaryEntry summaryEntry) {
- Contract.Requires(impl != null);
- Contract.Requires(summaryEntry != null);
- if (CommandLineOptions.Clo.IntraproceduralInfer) {
- return; // no summary to adjust
- }
-
- // compute the procedure invariant by joining all terminal block invariants...
- AI.Lattice.Element post = lattice.Bottom;
- foreach (Block block in impl.Blocks) {
- if (block.TransferCmd is ReturnCmd) {
- // note: if program control cannot reach this block, then postValue will be null
- if (block.PostInvariant != null) {
- post = (AI.Lattice.Element)lattice.Join(post, block.PostInvariant);
- }
- }
- }
-
- AI.Lattice.Element atReturn = post;
- foreach (Variable var in impl.LocVars) {
- Contract.Assert(var != null);
- atReturn = this.lattice.Eliminate(atReturn, var);
- }
- foreach (Variable var in impl.InParams) {
- Contract.Assert(var != null);
- atReturn = this.lattice.Eliminate(atReturn, var);
- }
-
- if (!this.lattice.LowerThan(atReturn, summaryEntry.OnExit)) {
- // If the results of this analysis are strictly worse than
- // what we previous knew for the same input assumptions,
- // update the summary and re-do the call sites.
-
- summaryEntry.OnExit = this.lattice.Join(summaryEntry.OnExit, atReturn);
-
- foreach (CallSite callSite in summaryEntry.ReturnPoints) {
- Contract.Assert(callSite != null);
- this.callReturnWorkItems.Enqueue(callSite);
- }
- }
- }
-
- private static int freshVarId = 0;
- private static Variable FreshVar(Boogie.Type ty) {
- Contract.Requires(ty != null);
- Contract.Ensures(Contract.Result<Variable>() != null);
-
- Variable fresh = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "fresh" + freshVarId, ty));
- freshVarId++;
- return fresh;
- }
-
- private delegate CallSite/*!*/ MarkCallSite(AI.Lattice.Element/*!*/ currentValue);
-
- /// <summary>
- /// Given a basic block, it propagates the abstract state at the entry point through the exit point of the block
- /// <param name="impl"> The implementation that owns the block </param>
- /// <param name="block"> The from where we propagate </param>
- /// <param name="statementIndex"> </param>
- /// <param name="currentValue"> The initial value </param>
- /// </summary>
- private void PropagateStartingAtStatement(Implementation/*!*/ impl, Block/*!*/ block, int statementIndex, AI.Lattice.Element/*!*/ currentValue,
- ProcedureSummaryEntry/*!*/ summaryEntry) {
- Contract.Requires(impl != null);
- Contract.Requires(block != null);
- Contract.Requires(currentValue != null);
- Contract.Requires(summaryEntry != null);
- Contract.Assume(cce.IsPeerConsistent(log));
- log.DbgMsg(string.Format("{0}:", block.Label));
- log.DbgMsgIndent();
-
- #region Apply the abstract transition relation to the statements in the block
- for (int cmdIndex = statementIndex; cmdIndex < block.Cmds.Length; cmdIndex++) {
- Cmd cmd = cce.NonNull(block.Cmds[cmdIndex]); // Fetch the command
- currentValue = Step(cmd, currentValue, impl, // Apply the transition function
- delegate(AI.Lattice.Element cv) {
- Contract.Requires(cv != null);
- return new CallSite(impl, block, cmdIndex, cv, summaryEntry);
- }
- );
- }
-
- block.PostInvariant = currentValue; // The invariant at the exit point of the block is that of the last statement
-
- log.DbgMsg(string.Format("pre {0}", cce.NonNull(block.PreInvariant).ToString()));
- log.DbgMsg(string.Format("post {0}", (block.PostInvariant).ToString()));
- log.DbgMsgUnindent();
- #endregion
- #region Propagate the post-condition to the successor nodes
- GotoCmd @goto = block.TransferCmd as GotoCmd;
- if (@goto != null) {
- // labelTargets is non-null after calling Resolve in a prior phase.
- Contract.Assume(@goto.labelTargets != null);
-
- // For all the successors of this block, propagate the abstract state
- foreach (Block succ in @goto.labelTargets) {
- Contract.Assert(succ != null);
- if (impl.Blocks.Contains(succ)) {
- succ.Lattice = block.Lattice; // The lattice is the same
- // Propagate the post-abstract state of this block to the successor
- ComputeBlockInvariants(impl, succ, block.PostInvariant, summaryEntry);
- }
- }
- }
- #endregion
- }
-
- /// <summary>
- /// The abstract transition relation.
- /// </summary>
- private AI.Lattice.Element Step(Cmd cmd, AI.Lattice.Element pre, Implementation impl, MarkCallSite/*?*/ callSiteMarker) {
- Contract.Requires(cmd != null);
- Contract.Requires(pre != null);
- Contract.Requires(impl != null);
- Contract.Ensures(Contract.Result<AI.Lattice.Element>() != null);
-
- Contract.Assume(cce.IsPeerConsistent(log));
- log.DbgMsg(string.Format("{0}", cmd));
- log.DbgMsgIndent();
-
- AI.Lattice.Element currentValue = pre;//Nonnullability was a precondition
-
- // Case split...
- #region AssignCmd
- if (cmd is AssignCmd) { // parallel assignment
- // we first eliminate map assignments
- AssignCmd assmt = cce.NonNull((AssignCmd)cmd).AsSimpleAssignCmd;
- //PM: Assume variables have been resolved
- Contract.Assume(Contract.ForAll<AssignLhs>(assmt.Lhss, lhs => lhs.DeepAssignedVariable != null));//TODO: Check my work, please, Mike.
-
- List<IdentifierExpr/*!>!*/> freshLhs = new List<IdentifierExpr/*!*/>();
- foreach (AssignLhs lhs in assmt.Lhss) {
- Contract.Assert(lhs != null);
- freshLhs.Add(Expr.Ident(FreshVar(cce.NonNull(lhs.DeepAssignedVariable)
- .TypedIdent.Type)));
- }
-
- for (int i = 0; i < freshLhs.Count; ++i)
- currentValue =
- this.lattice.Constrain(currentValue,
- Expr.Eq(freshLhs[i], assmt.Rhss[i]).IExpr);
- foreach (AssignLhs lhs in assmt.Lhss) {
- Contract.Assert(lhs != null);
- currentValue =
- this.lattice.Eliminate(currentValue, cce.NonNull(lhs.DeepAssignedVariable));
- }
- for (int i = 0; i < freshLhs.Count; ++i)
- currentValue =
- this.lattice.Rename(currentValue, cce.NonNull(freshLhs[i].Decl),
- cce.NonNull(assmt.Lhss[i].DeepAssignedVariable));
- }
-
- /*
- if (cmd is SimpleAssignCmd)
- {
- SimpleAssignCmd! assmt = (SimpleAssignCmd)cmd;
- assume assmt.Lhs.Decl != null; //PM: Assume variables have been resolved
- Variable! dest = assmt.Lhs.Decl;
- Variable! fresh = FreshVar(dest.TypedIdent.Type);
- IdentifierExpr newLhs = Expr.Ident(fresh);
- Expr equality = Expr.Eq(newLhs, assmt.Rhs);
-
- currentValue = this.lattice.Constrain(currentValue, equality.IExpr);
- currentValue = this.lattice.Eliminate(currentValue, dest);
- currentValue = this.lattice.Rename(currentValue, fresh, dest);
- }
- #endregion
- #region ArrayAssignCmd
- else if (cmd is ArrayAssignCmd)
- {
- ArrayAssignCmd assmt = (ArrayAssignCmd)cmd;
-
- assume assmt.Array.Type != null; //PM: assume that type checker has run
- ArrayType! arrayType = (ArrayType)assmt.Array.Type;
-
- Variable newHeapVar = FreshVar(arrayType);
- IdentifierExpr newHeap = Expr.Ident(newHeapVar);
- IdentifierExpr oldHeap = assmt.Array;
- assume oldHeap.Decl != null; //PM: assume that variable has been resolved
-
- // For now, we only know how to handle heaps
- if (arrayType.IndexType0.IsRef && arrayType.IndexType1 != null && arrayType.IndexType1.IsName)
- {
- //PM: The following assertion follows from a nontrivial invariant of ArrayAssignCmd,
- //PM: which we do not have yet. Therefore, we put in an assume fo now.
- assume assmt.Index1 != null;
- assert assmt.Index1 != null;
- // heap succession predicate
- Expr heapsucc = Expr.HeapSucc(oldHeap, newHeap, assmt.Index0, assmt.Index1);
-
- currentValue = this.lattice.Constrain(currentValue, heapsucc.IExpr);
-
- }
- else
- {
- // TODO: We can do this case as well if the heap succession array can handle non-heap arrays
- }
- // new select expression
- IndexedExpr newLhs = new IndexedExpr(Token.NoToken, newHeap, assmt.Index0, assmt.Index1);
- Expr equality = Expr.Eq(newLhs, assmt.Rhs);
-
- currentValue = this.lattice.Constrain(currentValue, equality.IExpr);
- currentValue = this.lattice.Eliminate(currentValue, oldHeap.Decl);
- currentValue = this.lattice.Rename(currentValue, newHeapVar, oldHeap.Decl);
-
-
- } */
- #endregion
- #region Havoc
- else if (cmd is HavocCmd) {
- HavocCmd havoc = (HavocCmd)cmd;
- foreach (IdentifierExpr id in havoc.Vars) {
- Contract.Assert(id != null);
- currentValue = this.lattice.Eliminate(currentValue, cce.NonNull(id.Decl));
- }
- }
- #endregion
- #region PredicateCmd
- else if (cmd is PredicateCmd) {
- //System.Console.WriteLine("Abstract State BEFORE " + ((PredicateCmd) cmd).Expr + " : " +this.lattice.ToPredicate(currentValue));
-
- Expr embeddedExpr = cce.NonNull((PredicateCmd)cmd).Expr;
- List<Expr/*!>!*/> conjuncts = flatConjunction(embeddedExpr); // Handle "assume P && Q" as if it was "assume P; assume Q"
- Contract.Assert(conjuncts != null);
- foreach (Expr c in conjuncts) {
- Contract.Assert(c != null);
- currentValue = this.lattice.Constrain(currentValue, c.IExpr);
- }
-
- //System.Console.WriteLine("Abstract State AFTER assert/assume "+ this.lattice.ToPredicate(currentValue));
- }
- #endregion
- #region CallCmd
- else if (cmd is CallCmd) {
- CallCmd call = (CallCmd)cmd;
-
- if (!CommandLineOptions.Clo.IntraproceduralInfer) {
- // Interprocedural analysis
-
- if (callSiteMarker == null) {
- throw new System.InvalidOperationException("INTERNAL ERROR: Context does not allow CallCmd.");
- }
-
- CallSite here = callSiteMarker(currentValue);
- currentValue = ApplyProcedureSummary(call, impl, currentValue, here);
- } else {
- // Intraprocedural analysis
-
- StateCmd statecmd = call.Desugaring as StateCmd;
- if (statecmd != null) {
- // Iterate the abstract transition on all the commands in the desugaring of the call
- foreach (Cmd callDesug in statecmd.Cmds) {
- Contract.Assert(callDesug != null);
- currentValue = Step(callDesug, currentValue, impl, null);
- }
-
- // Now, project out the local variables
- foreach (Variable local in statecmd.Locals) {
- Contract.Assert(local != null);
- currentValue = this.lattice.Eliminate(currentValue, local);
- }
- } else
- throw new System.InvalidOperationException("INTERNAL ERROR: CallCmd does not desugar to StateCmd.");
- }
- }
- #endregion
- #region CommentCmd
- else if (cmd is CommentCmd) {
- // skip
- }
- #endregion
- else if (cmd is SugaredCmd) {
- // other sugared commands are treated like their desugaring
- SugaredCmd sugar = (SugaredCmd)cmd;
- Cmd desugaring = sugar.Desugaring;
- if (desugaring is StateCmd) {
- StateCmd statecmd = (StateCmd)desugaring;
- // Iterate the abstract transition on all the commands in the desugaring of the call
- foreach (Cmd callDesug in statecmd.Cmds) {
- Contract.Assert(callDesug != null);
- currentValue = Step(callDesug, currentValue, impl, null);
- }
- // Now, project out the local variables
- foreach (Variable local in statecmd.Locals) {
- Contract.Assert(local != null);
- currentValue = this.lattice.Eliminate(currentValue, local);
- }
- } else {
- currentValue = Step(desugaring, currentValue, impl, null);
- }
- } else {
- Contract.Assert(false); // unknown command
- throw new cce.UnreachableException();
- }
-
- log.DbgMsgUnindent();
-
- return currentValue;
- }
-
- /// <summary>
- /// Flatten an expresion in the form P AND Q ... AND R into a list [P, Q, ..., R]
- /// </summary>
- private List<Expr/*!>!*/> flatConjunction(Expr embeddedExpr) {
- Contract.Requires(embeddedExpr != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Expr>>()));
-
- var retValue = new List<Expr/*!*/>();
- NAryExpr e = embeddedExpr as NAryExpr;
- if (e != null && e.Fun.FunctionName.CompareTo("&&") == 0) { // if it is a conjunction
- foreach (Expr arg in e.Args) {
- Contract.Assert(arg != null);
- var newConjuncts = flatConjunction(arg);
- retValue.AddRange(newConjuncts);
- }
- } else {
- retValue.Add(embeddedExpr);
- }
- return retValue;
- }
-
- /// <summary>
- /// Compute the invariants for a basic block
- /// <param name="impl"> The implementation the block belongs to </param>
- /// <param name="block"> The block for which we compute the invariants </param>
- /// <param name="incomingValue"> The "init" abstract state for the block </param>
- /// </summary>
- private void ComputeBlockInvariants(Implementation impl, Block block, AI.Lattice.Element incomingValue, ProcedureSummaryEntry summaryEntry) {
- Contract.Requires(impl != null);
- Contract.Requires(block != null);
- Contract.Requires(incomingValue != null);
- Contract.Requires(summaryEntry != null);
- if (block.PreInvariant == null) // block has not yet been processed
- {
- Contract.Assert(block.PostInvariant == null);
-
- // To a first approximation the block is unreachable
- block.PreInvariant = this.lattice.Bottom;
- block.PostInvariant = this.lattice.Bottom;
- }
-
- Contract.Assert(block.PreInvariant != null);
- Contract.Assert(block.PostInvariant != null);
-
- #region Check if we have reached a postfixpoint
-
- if (lattice.LowerThan(incomingValue, block.PreInvariant)) {
- // We have reached a post-fixpoint, so we are done...
-#if DEBUG_PRINT
- System.Console.WriteLine("@@ Compared for block {0}:", block.Label);
- System.Console.WriteLine("@@ {0}", lattice.ToPredicate(incomingValue));
- System.Console.WriteLine("@@ {0}", lattice.ToPredicate(block.PreInvariant));
- System.Console.WriteLine("@@ result = True");
- System.Console.WriteLine("@@ end Compare");
-#endif
- return;
- }
-#if DEBUG_PRINT
- // Compute the free variables in incoming and block.PreInvariant
- FreeVariablesVisitor freeVarsVisitorForA = new FreeVariablesVisitor();
- FreeVariablesVisitor freeVarsVisitorForB = new FreeVariablesVisitor();
-
- lattice.ToPredicate(incomingValue).DoVisit(freeVarsVisitorForA);
- lattice.ToPredicate(block.PreInvariant).DoVisit(freeVarsVisitorForB);
-
- List<AI.IVariable!>! freeVarsOfA = freeVarsVisitorForA.FreeVariables;
- List<AI.IVariable!>! freeVarsOfB = freeVarsVisitorForB.FreeVariables;
-
- System.Console.WriteLine("@@ Compared for block {0}:", block.Label);
- System.Console.WriteLine("@@ Incoming: {0}", lattice.ToPredicate((!) incomingValue));
- System.Console.WriteLine("@@ Free Variables : {0}", ToString(freeVarsOfA));
- System.Console.WriteLine("@@ Previous: {0}", lattice.ToPredicate(block.PreInvariant));
- System.Console.WriteLine("@@ Free Variables : {0}", ToString(freeVarsOfB));
- System.Console.WriteLine("@@ result = False");
- System.Console.WriteLine("@@ end Compare");
- string operation = "";
-#endif
- #endregion
- #region If it is not the case, then join or widen the incoming abstract state with the previous one
- if (block.widenBlock) // If the considered block is the entry point of a loop
- {
- if (block.iterations <= CommandLineOptions.Clo.StepsBeforeWidening + 1) {
-#if DEBUG_PRINT
- operation = "join";
-#endif
- block.PreInvariant = (AI.Lattice.Element)lattice.Join(block.PreInvariant, incomingValue);
- } else {
-#if DEBUG_PRINT
- operation = "widening";
-#endif
-
- // The default is to have have a widening that perform a (approximation of) the closure of the operands, so to improve the precision
- // block.PreInvariant = WideningWithClosure.MorePreciseWiden(lattice, (!) block.PreInvariant, incomingValue);
- block.PreInvariant = (AI.Lattice.Element)lattice.Widen(block.PreInvariant, incomingValue);
- }
- block.iterations++;
- } else {
-#if DEBUG_PRINT
- operation = "join";
-#endif
- block.PreInvariant = (AI.Lattice.Element)lattice.Join(block.PreInvariant, incomingValue);
- }
-
-#if DEBUG_PRINT
- System.Console.WriteLine("@@ {0} for block {1}:", operation, block.Label);
- System.Console.WriteLine("@@ {0}", lattice.ToPredicate(block.PreInvariant));
- System.Console.WriteLine("@@ end");
-#endif
- #endregion
- #region Propagate the entry abstract state through the method
- PropagateStartingAtStatement(impl, block, 0, cce.NonNull(block.PreInvariant.Clone()), summaryEntry);
- #endregion
- }
-
-#if DEBUG_PRINT
- private string! ToString(List<AI.IVariable!>! vars)
- {
- string s = "";
-
- foreach(AI.IVariable! v in vars)
- {
- s += v.Name +" ";
- }
- return s;
- }
-#endif
-
- } // class
-
-
- /// <summary>
- /// Defines a class for building the abstract domain according to the parameters switch
- /// </summary>
- public class AbstractDomainBuilder {
-
- private AbstractDomainBuilder() { /* do nothing */
- }
-
- /// <summary>
- /// Return a fresh instance of the abstract domain of intervals
- /// </summary>
- static public AbstractAlgebra BuildIntervalsAbstractDomain() {
- Contract.Ensures(Contract.Result<AbstractAlgebra>() != null);
-
- AI.IPropExprFactory propfactory = new BoogiePropFactory();
- AI.ILinearExprFactory linearfactory = new BoogieLinearFactory();
- AI.IValueExprFactory valuefactory = new BoogieValueFactory();
- IComparer variableComparer = new VariableComparer();
-
- AbstractAlgebra retAlgebra;
- AI.Lattice intervals = new AI.VariableMapLattice(propfactory, valuefactory, new AI.IntervalLattice(linearfactory), variableComparer);
- Contract.Assert(intervals != null);
- retAlgebra = new AbstractAlgebra(intervals, propfactory, linearfactory, null, valuefactory, null, variableComparer);
-
- return retAlgebra;
- }
-
- /// <summary>
- /// Return a fresh abstract domain, according to the parameters specified by the command line
- /// </summary>
- static public AbstractAlgebra BuildAbstractDomain() {
- Contract.Ensures(Contract.Result<AbstractAlgebra>() != null);
-
- AbstractAlgebra retAlgebra;
-
- AI.Lattice returnLattice;
-
- AI.IPropExprFactory propfactory = new BoogiePropFactory();
- AI.ILinearExprFactory linearfactory = new BoogieLinearFactory();
- AI.IIntExprFactory intfactory = new BoogieIntFactory();
- AI.IValueExprFactory valuefactory = new BoogieValueFactory();
- AI.INullnessFactory nullfactory = new BoogieNullnessFactory();
- IComparer variableComparer = new VariableComparer();
-
- AI.MultiLattice multilattice = new AI.MultiLattice(propfactory, valuefactory);
-
- if (CommandLineOptions.Clo.Ai.Intervals) // Intervals
- {
- multilattice.AddLattice(new AI.VariableMapLattice(propfactory, valuefactory,
- new AI.IntervalLattice(linearfactory),
- variableComparer));
- }
- if (CommandLineOptions.Clo.Ai.Constant) // Constant propagation
-
- {
- multilattice.AddLattice(new AI.VariableMapLattice(propfactory, valuefactory,
- new AI.ConstantLattice(intfactory),
- variableComparer));
- }
- if (CommandLineOptions.Clo.Ai.DynamicType) // Class types
- {
- BoogieTypeFactory typeFactory = new BoogieTypeFactory();
- multilattice.AddLattice(new AI.VariableMapLattice(propfactory, valuefactory,
- new AI.DynamicTypeLattice(typeFactory, propfactory),
- variableComparer));
- }
- if (CommandLineOptions.Clo.Ai.Nullness) // Nullness
- {
- multilattice.AddLattice(new AI.VariableMapLattice(propfactory, valuefactory,
- new AI.NullnessLattice(nullfactory),
- variableComparer));
- }
- if (CommandLineOptions.Clo.Ai.Polyhedra) // Polyhedra
- {
- multilattice.AddLattice(new AI.PolyhedraLattice(linearfactory, propfactory));
- }
-
-
- returnLattice = multilattice;
- if (CommandLineOptions.Clo.Ai.DebugStatistics) {
- returnLattice = new AI.StatisticsLattice(returnLattice);
- }
-
- returnLattice.Validate();
-
- retAlgebra = new AbstractAlgebra(returnLattice, propfactory, linearfactory, intfactory, valuefactory, nullfactory,
- variableComparer);
-
- return retAlgebra;
-
- }
- }
-
- /// <summary>
- /// An Abstract Algebra is a tuple made of a Lattice and several factories
- /// </summary>
- public class AbstractAlgebra {
- [Peer]
- private AI.Lattice lattice;
- [Peer]
- private AI.IPropExprFactory propFactory;
- [Peer]
- private AI.ILinearExprFactory linearFactory;
- [Peer]
- private AI.IIntExprFactory intFactory;
- [Peer]
- private AI.IValueExprFactory valueFactory;
- [Peer]
- private AI.INullnessFactory nullFactory;
- [Peer]
- private IComparer variableComparer;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(lattice != null);
- }
-
- public AI.Lattice Lattice {
- get {
- Contract.Ensures(Contract.Result<AI.Lattice>() != null);
-
- return lattice;
- }
- }
-
- public AI.IPropExprFactory PropositionFactory {
- get {
- return this.propFactory;
- }
- }
-
- public AI.ILinearExprFactory LinearExprFactory {
- get {
- return this.linearFactory;
- }
- }
-
- public AI.IIntExprFactory IntExprFactory {
- get {
- return this.intFactory;
- }
- }
-
- public AI.IValueExprFactory ValueFactory {
- get {
- return this.valueFactory;
- }
- }
-
- public AI.INullnessFactory NullFactory {
- get {
- return this.nullFactory;
- }
- }
-
- public IComparer VariableComparer {
- get {
- return this.variableComparer;
- }
- }
-
- [Captured]
- public AbstractAlgebra(AI.Lattice lattice,
- AI.IPropExprFactory propFactory,
- AI.ILinearExprFactory linearFactory,
- AI.IIntExprFactory intFactory,
- AI.IValueExprFactory valueFactory,
- AI.INullnessFactory nullFactory,
- IComparer variableComparer) {
- Contract.Requires(propFactory == null || cce.Owner.Same(lattice, propFactory));//TODO: Owner is Microsoft.Contracts (mscorlib.Contracts).Owner
- Contract.Requires(linearFactory == null || cce.Owner.Same(lattice, linearFactory));
- Contract.Requires(intFactory == null || cce.Owner.Same(lattice, intFactory));
- Contract.Requires(valueFactory == null || cce.Owner.Same(lattice, valueFactory));
- Contract.Requires(nullFactory == null || cce.Owner.Same(lattice, nullFactory));
- Contract.Requires(variableComparer == null || cce.Owner.Same(lattice, variableComparer));
- // ensures Owner.Same(this, lattice); // KRML:
-
- Contract.Requires(lattice != null);
- this.lattice = lattice;
-
- this.propFactory = propFactory;
- this.linearFactory = linearFactory;
- this.intFactory = intFactory;
- this.valueFactory = valueFactory;
- this.nullFactory = nullFactory;
- this.variableComparer = variableComparer;
- }
-
- }
-
- public class AbstractInterpretation {
- /// <summary>
- /// Run the abstract interpretation.
- /// It has two entry points. One is the RunBoogie method. The other is the CCI PlugIn
- /// </summary>
- public static void RunAbstractInterpretation(Program program) {
- Contract.Requires(program != null);
- Helpers.ExtraTraceInformation("Starting abstract interpretation");
-
- if (CommandLineOptions.Clo.UseAbstractInterpretation) {
- DateTime start = new DateTime(); // to please compiler's definite assignment rules
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine();
- Console.WriteLine("Running abstract interpretation...");
- start = DateTime.UtcNow;
- }
-
- WidenPoints.Compute(program);
-
- if (CommandLineOptions.Clo.Ai.AnySet) // if there is some user defined domain we override the default (= intervals)
- {
- AI.Lattice lattice = AbstractDomainBuilder.BuildAbstractDomain().Lattice;
- ApplyAbstractInterpretation(program, lattice);
-
- if (CommandLineOptions.Clo.Ai.DebugStatistics) {
- Console.Error.WriteLine(lattice);
- }
- } else // Otherwise the default is the use of the abstract domain of intervals (useful for simple for loops)
- {
- AI.Lattice lattice = AbstractDomainBuilder.BuildIntervalsAbstractDomain().Lattice;
- Contract.Assert(lattice != null);
- ApplyAbstractInterpretation(program, lattice);
- }
-
- program.InstrumentWithInvariants();
-
- if (CommandLineOptions.Clo.Trace) {
- DateTime end = DateTime.UtcNow;
- TimeSpan elapsed = end - start;
- Console.WriteLine(" [{0} s]", elapsed.TotalSeconds);
- Console.Out.Flush();
- }
- }
- }
-
- static void ApplyAbstractInterpretation(Program program, AI.Lattice lattice) {
- Contract.Requires(program != null);
- Contract.Requires(lattice != null);
- AbstractionEngine engine = new AbstractionEngine(lattice);
- engine.ComputeProgramInvariants(program);
- }
- }
-
-} // namespace \ No newline at end of file
diff --git a/Source/AbsInt/ExprFactories.cs b/Source/AbsInt/ExprFactories.cs
deleted file mode 100644
index 9b1ea0a0..00000000
--- a/Source/AbsInt/ExprFactories.cs
+++ /dev/null
@@ -1,275 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using Microsoft.Boogie;
-using AI = Microsoft.AbstractInterpretationFramework;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-namespace Microsoft.Boogie.AbstractInterpretation {
-
- public class BoogiePropFactory : BoogieFactory, AI.IPropExprFactory
- {
- public AI.IFunApp False {
- get {
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
-
- return Expr.False;
- }
- }
- public AI.IFunApp True {
- get {
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
-
- return Expr.True;
- }
- }
-
- public AI.IFunApp Not(AI.IExpr p) {
- //Contract.Requires(p != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
-
- return Expr.Unary(Token.NoToken, UnaryOperator.Opcode.Not, IExpr2Expr(p));
- }
-
- public AI.IFunApp And(AI.IExpr p, AI.IExpr q) {
- //Contract.Requires(p != null);
- //Contract.Requires(q != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
-
- return Expr.Binary(BinaryOperator.Opcode.And, IExpr2Expr(p), IExpr2Expr(q));
- }
-
- public AI.IFunApp Or(AI.IExpr p, AI.IExpr q) {
- //Contract.Requires(p != null);
- //Contract.Requires(q != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- return Expr.Binary(BinaryOperator.Opcode.Or, IExpr2Expr(p), IExpr2Expr(q));
- }
-
- public AI.IFunApp Implies(AI.IExpr p, AI.IExpr q) {
- //Contract.Requires(p != null);
- //Contract.Requires(q != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- return Expr.Binary(BinaryOperator.Opcode.Imp, IExpr2Expr(p), IExpr2Expr(q));
- }
-
- public AI.IFunApp Exists(AI.IFunction p) {
- //Contract.Requires(p != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
-
- return (AI.IFunApp)(new ExistsExpr(Token.NoToken, new VariableSeq((Variable)p.Param), IExpr2Expr(p.Body))).IExpr;
- }
-
- public AI.IFunApp Forall(AI.IFunction p) {
- //Contract.Requires(p != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
-
- return (AI.IFunApp)(new ForallExpr(Token.NoToken, new VariableSeq((Variable)p.Param), IExpr2Expr(p.Body))).IExpr;
- }
- }
-
- public class BoogieValueFactory : BoogieFactory, AI.IValueExprFactory {
- public AI.IFunApp Eq(AI.IExpr e0, AI.IExpr e1) {
- //Contract.Requires(e0 != null);
- //Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
-
- return Expr.Eq(IExpr2Expr(e0), IExpr2Expr(e1));
- }
- public AI.IFunApp Neq(AI.IExpr e0, AI.IExpr e1) {
- //Contract.Requires(e0 != null);
- //Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- return Expr.Neq(IExpr2Expr(e0), IExpr2Expr(e1));
- }
- }
-
- public class BoogieNullnessFactory : BoogieFactory, AI.INullnessFactory {
- public AI.IFunApp Eq(AI.IExpr e0, AI.IExpr e1) {
- //Contract.Requires(e0 != null);
- //Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- return Expr.Eq(IExpr2Expr(e0), IExpr2Expr(e1));
- }
-
- public AI.IFunApp Neq(AI.IExpr e0, AI.IExpr e1) {
- //Contract.Requires(e0 != null);
- //Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- return Expr.Neq(IExpr2Expr(e0), IExpr2Expr(e1));
- }
-
- public AI.IFunApp Null {
- get {
- Contract.Assert(false); // don't know where to get null from\
- throw new cce.UnreachableException();
- }
- }
- }
-
- public class BoogieIntFactory : BoogieValueFactory, AI.IIntExprFactory {
- public AI.IFunApp Const(BigNum i) {
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
-
- return new LiteralExpr(Token.NoToken, i);
- }
- }
-
- public class BoogieLinearFactory : BoogieIntFactory, AI.ILinearExprFactory {
- public AI.IFunApp AtMost(AI.IExpr e0, AI.IExpr e1) {
- //Contract.Requires(e0 != null);
- //Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- return Expr.Le(IExpr2Expr(e0), IExpr2Expr(e1));
- }
- public AI.IFunApp Add(AI.IExpr e0, AI.IExpr e1) {
- //Contract.Requires(e0 != null);
- //Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- return Expr.Add(IExpr2Expr(e0), IExpr2Expr(e1));
- }
- public AI.IExpr Term(Rational r, AI.IVariable var) {
- Contract.Ensures(Contract.Result<AI.IExpr>() != null);
-
- if (var != null && r == Rational.ONE) {
- return var;
- } else {
- Expr product;
- if (r.IsIntegral) {
- product = Expr.Literal(r.AsBigNum);
- } else {
- product = Expr.Div(Expr.Literal(r.Numerator), Expr.Literal(r.Denominator));
- }
- if (var != null) {
- product = Expr.Mul(product, IExpr2Expr(var));
- }
- return product.IExpr;
- }
- }
-
- public AI.IFunApp False {
- get {
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
-
- return Expr.False;
- }
- }
- public AI.IFunApp True {
- get {
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
-
- return Expr.True;
- }
- }
- public AI.IFunApp And(AI.IExpr p, AI.IExpr q) {
- //Contract.Requires(p != null);
- //Contract.Requires(q != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
-
- return Expr.Binary(BinaryOperator.Opcode.And, IExpr2Expr(p), IExpr2Expr(q));
- }
- }
-
- public class BoogieTypeFactory : BoogieFactory, AI.ITypeExprFactory {
- /// <summary>
- /// Returns an expression denoting the top of the type hierarchy.
- /// </summary>
- public AI.IExpr RootType {
- get {
- Contract.Assert(false); // BUGBUG: TODO
- throw new System.NotImplementedException();
- }
- }
-
- /// <summary>
- /// Returns true iff "t" denotes a type constant.
- /// </summary>
- [Pure]
- public bool IsTypeConstant(AI.IExpr t) {
- //Contract.Requires(t != null);
- Contract.Ensures(Contract.Result<bool>() == (t is Constant));
- return t is Constant;
- }
-
- /// <summary>
- /// Returns true iff t0 and t1 are types such that t0 and t1 are equal.
- /// </summary>
- [Pure]
- public bool IsTypeEqual(AI.IExpr t0, AI.IExpr t1) {
- //Contract.Requires(t0 != null);
- //Contract.Requires(t1 != null);
- Constant c0 = t0 as Constant;
- Constant c1 = t1 as Constant;
- return c0 != null && c1 != null && c0 == c1;
- }
-
- /// <summary>
- /// Returns true iff t0 and t1 are types such that t0 is a subtype of t1.
- /// </summary>
- [Pure]
- public bool IsSubType(AI.IExpr t0, AI.IExpr t1) {
- //Contract.Requires(t0 != null);
- //Contract.Requires(t1 != null);
-
- Contract.Assert(false); // BUGBUG: TODO
- throw new cce.UnreachableException();
- }
-
- /// <summary>
- /// Returns the most derived supertype of both "t0" and "t1". A precondition is
- /// that "t0" and "t1" both represent types.
- /// </summary>
- public AI.IExpr JoinTypes(AI.IExpr t0, AI.IExpr t1) {
- //Contract.Requires(t0 != null);
- //Contract.Requires(t1 != null);
- Contract.Ensures(Contract.Result<AI.IExpr>() != null);
-
-
- Contract.Assert(false); // BUGBUG: TODO
- throw new cce.UnreachableException();
- }
-
- public AI.IFunApp IsExactlyA(AI.IExpr e, AI.IExpr type) {
- //PM: We need this assume because Boogie does not yet allow us to use the
- //PM: inherited precondition "requires IsTypeConstant(type)".
- //PM: Note that that precondition is currently commented out.
- //Contract.Requires(e != null);
- //Contract.Requires(type != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
-
- Contract.Assume(type is Constant);
- Constant theType = (Constant)type;
- Contract.Assert(false);
- throw new cce.UnreachableException();
- Expr typeofExpr = new NAryExpr(Token.NoToken,
- new FunctionCall(new IdentifierExpr(Token.NoToken, "$typeof", Type.Int // Name
- )),
- new ExprSeq(IExpr2Expr(e)));
- return Expr.Eq(typeofExpr, Expr.Ident(theType));
- }
-
- public AI.IFunApp IsA(AI.IExpr e, AI.IExpr type) {
- //Contract.Requires(e != null);
- //Contract.Requires(type != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- //PM: We need this assume because Boogie does not yet allow us to use the
- //PM: inherited precondition "requires IsTypeConstant(type)".
- //PM: Note that that precondition is currently commented out.
-
-
- Contract.Assume(type is Constant);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- Expr typeofExpr = new NAryExpr(Token.NoToken,
- new FunctionCall(new IdentifierExpr(Token.NoToken, "$typeof", Type.Int // Name
- )),
- new ExprSeq(IExpr2Expr(e)));
- return new NAryExpr(Token.NoToken,
- new BinaryOperator(Token.NoToken, BinaryOperator.Opcode.Subtype),
- new ExprSeq(typeofExpr, IExpr2Expr(e)));
- }
- }
-}
diff --git a/Source/AbsInt/IntervalDomain.cs b/Source/AbsInt/IntervalDomain.cs
index 247a357d..51391105 100644
--- a/Source/AbsInt/IntervalDomain.cs
+++ b/Source/AbsInt/IntervalDomain.cs
@@ -632,6 +632,10 @@ namespace Microsoft.Boogie.AbstractInterpretation
var n = ((BigNum)node.Val).ToBigInteger;
Lo = n;
Hi = n + 1;
+ } else if (node.Val is BigDec) {
+ var n = ((BigDec)node.Val).Floor(-BigInteger.Pow(10, 12), BigInteger.Pow(10, 12));
+ Lo = n;
+ Hi = n + 1;
} else if (node.Val is bool) {
if ((bool)node.Val) {
// true
@@ -646,7 +650,7 @@ namespace Microsoft.Boogie.AbstractInterpretation
return node;
}
public override Expr VisitIdentifierExpr(IdentifierExpr node) {
- if (node.Type.IsBool || node.Type.IsInt) {
+ if (node.Type.IsBool || node.Type.IsInt || node.Type.IsReal) {
Node.GetBounds(N, node.Decl, out Lo, out Hi);
}
return node;
@@ -655,7 +659,18 @@ namespace Microsoft.Boogie.AbstractInterpretation
if (node.Fun is UnaryOperator) {
var op = (UnaryOperator)node.Fun;
Contract.Assert(node.Args.Length == 1);
- if (op.Op == UnaryOperator.Opcode.Not) {
+ if (op.Op == UnaryOperator.Opcode.Neg) {
+ BigInteger? lo, hi;
+ VisitExpr(node.Args[0]);
+ lo = Lo; hi = Hi;
+ if (hi != null) {
+ Lo = 1 - hi;
+ }
+ if (lo != null) {
+ Hi = -lo;
+ }
+ }
+ else if (op.Op == UnaryOperator.Opcode.Not) {
VisitExpr(node.Args[0]);
Contract.Assert((Lo == null && Hi == null) ||
(Lo == null && (BigInteger)Hi == 1) ||
@@ -803,6 +818,20 @@ namespace Microsoft.Boogie.AbstractInterpretation
Hi = hi1;
}
break;
+ case BinaryOperator.Opcode.RealDiv:
+ // this uses an incomplete approximation that could be tightened up
+ if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) {
+ Lo = new BigInteger(0);
+ Hi = hi1;
+ }
+ break;
+ case BinaryOperator.Opcode.Pow:
+ // this uses an incomplete approximation that could be tightened up
+ if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) {
+ Lo = new BigInteger(0);
+ Hi = hi1;
+ }
+ break;
default:
break;
}
diff --git a/Source/AbsInt/LoopInvariantsOnDemand.cs b/Source/AbsInt/LoopInvariantsOnDemand.cs
deleted file mode 100644
index b61b1445..00000000
--- a/Source/AbsInt/LoopInvariantsOnDemand.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.Boogie.AbstractInterpretation {
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics.Contracts;
- using AI = Microsoft.AbstractInterpretationFramework;
- using Boogie = Microsoft.Boogie;
-
-
-
- /// <summary>
- /// A visitor of an abstract interpretation expression that collects the free variables
- /// </summary>
- class FreeVariablesVisitor : AI.ExprVisitor {
- [Peer]
- List<AI.IVariable> variables;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(variables));
- Contract.Invariant(cce.NonNullElements(varNames));
- }
-
- public List<AI.IVariable> FreeVariables {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<AI.IVariable>>()));
-
- return this.variables;
- }
- }
-
- List<string> varNames; // used to check the consinstency!
-
- public FreeVariablesVisitor() {
- this.variables = new List<AI.IVariable>();
- this.varNames = new List<string>();
- }
-
- override public object Default(AI.IExpr expr) {
-
- if (expr is AI.IVariable) {
- if (!variables.Contains((AI.IVariable)expr)) {
- this.variables.Add((AI.IVariable)expr);
-
- Contract.Assert(!this.varNames.Contains(expr.ToString())); // If we get there, we have an error: two variables with the same name but different identity
-
- this.varNames.Add(expr.ToString());
- }
- return null;
- } else if (expr is AI.IFunApp)
- return VisitFunApp((AI.IFunApp)expr);
- else if (expr is AI.IFunction)
- return VisitFunction((AI.IFunction)expr);
- else if (expr is AI.IUnknown)
- return null;
- else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
-
- public override object VisitFunApp(AI.IFunApp funapp) {
-
- foreach (AI.IExpr arg in funapp.Arguments) {
- Contract.Assert(arg != null);
- arg.DoVisit(this);
- }
- return true;
- }
-
- public override object VisitFunction(AI.IFunction fun) {
- //Contract.Requires(fun != null);
- fun.Body.DoVisit(this);
- this.variables.Remove(fun.Param);
- return true;
- }
-
- }
-
-} \ No newline at end of file
diff --git a/Source/AbsInt/NativeLattice.cs b/Source/AbsInt/NativeLattice.cs
index f5bf1e03..4fccc14b 100644
--- a/Source/AbsInt/NativeLattice.cs
+++ b/Source/AbsInt/NativeLattice.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;
using Microsoft.Boogie;
@@ -95,7 +96,7 @@ namespace Microsoft.Boogie.AbstractInterpretation
}
if (lattice != null) {
- Dictionary<Procedure, Implementation[]> procedureImplementations = AbstractionEngine.ComputeProcImplMap(program);
+ Dictionary<Procedure, Implementation[]> procedureImplementations = ComputeProcImplMap(program);
ComputeProgramInvariants(program, procedureImplementations, lattice);
if (CommandLineOptions.Clo.Ai.DebugStatistics) {
Console.Error.WriteLine(lattice);
@@ -110,9 +111,22 @@ namespace Microsoft.Boogie.AbstractInterpretation
}
}
+ private static Dictionary<Procedure, Implementation[]> ComputeProcImplMap(Program program) {
+ Contract.Requires(program != null);
+ // Since implementations call procedures (impl. signatures)
+ // rather than directly calling other implementations, we first
+ // need to compute which implementations implement which
+ // procedures and remember which implementations call which
+ // procedures.
+
+ return program
+ .TopLevelDeclarations
+ .Where(d => d is Implementation).Select(i => (Implementation)i)
+ .GroupBy(i => i.Proc).Select(g => g.ToArray()).ToDictionary(a => a[0].Proc);
+ }
+
/// <summary>
- /// Compute and apply the invariants for the program using the underlying abstract domain (using native Boogie
- /// expressions, not the abstracted AI.Expr's).
+ /// Compute and apply the invariants for the program using the underlying abstract domain.
/// </summary>
public static void ComputeProgramInvariants(Program program, Dictionary<Procedure, Implementation[]> procedureImplementations, NativeLattice lattice) {
Contract.Requires(program != null);
diff --git a/Source/Basetypes/Basetypes.csproj b/Source/Basetypes/Basetypes.csproj
index ceccc5cf..a7b7cb71 100644
--- a/Source/Basetypes/Basetypes.csproj
+++ b/Source/Basetypes/Basetypes.csproj
@@ -148,6 +148,7 @@
<Compile Include="..\version.cs">
<Link>version.cs</Link>
</Compile>
+ <Compile Include="BigDec.cs" />
<Compile Include="BigNum.cs" />
<Compile Include="Rational.cs" />
<Compile Include="Set.cs" />
diff --git a/Source/Basetypes/BigDec.cs b/Source/Basetypes/BigDec.cs
new file mode 100644
index 00000000..6059539b
--- /dev/null
+++ b/Source/Basetypes/BigDec.cs
@@ -0,0 +1,313 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.Diagnostics.Contracts;
+
+
+namespace Microsoft.Basetypes {
+ using BIM = System.Numerics.BigInteger;
+
+
+ /// <summary>
+ /// A representation of decimal values.
+ /// </summary>
+ public struct BigDec {
+
+ // the internal representation
+ [Rep]
+ internal readonly BIM mantissa;
+ [Rep]
+ internal readonly int exponent;
+
+ public BIM Mantissa {
+ get {
+ return mantissa;
+ }
+ }
+
+ public int Exponent {
+ get {
+ return exponent;
+ }
+ }
+
+ public static readonly BigDec ZERO = FromInt(0);
+ private static readonly BIM ten = new BIM(10);
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Constructors
+
+ [Pure]
+ public static BigDec FromInt(int v) {
+ return new BigDec(v, 0);
+ }
+
+ [Pure]
+ public static BigDec FromString(string v) {
+ if (v == null) throw new FormatException();
+
+ BIM integral = BIM.Zero;
+ BIM fraction = BIM.Zero;
+ int exponent = 0;
+
+ int len = v.Length;
+
+ int i = v.IndexOf('e');
+ if (i >= 0) {
+ if (i + 1 == v.Length) throw new FormatException();
+ exponent = Int32.Parse(v.Substring(i + 1, len - i - 1));
+ len = i;
+ }
+
+ int fractionLen = 0;
+ i = v.IndexOf('.');
+ if (i >= 0) {
+ if (i + 1 == v.Length) throw new FormatException();
+ fractionLen = len - i - 1;
+ fraction = BIM.Parse(v.Substring(i + 1, fractionLen));
+ len = i;
+ }
+
+ integral = BIM.Parse(v.Substring(0, len));
+
+ if (!fraction.IsZero) {
+ while (fractionLen > 0) {
+ integral = integral * ten;
+ exponent = exponent - 1;
+ fractionLen = fractionLen - 1;
+ }
+ }
+
+ return new BigDec(integral + fraction, exponent);
+ }
+
+ internal BigDec(BIM mantissa, int exponent) {
+ if (mantissa.IsZero) {
+ this.mantissa = mantissa;
+ this.exponent = 0;
+ }
+ else {
+ while (mantissa % ten == BIM.Zero) {
+ mantissa = mantissa / ten;
+ exponent = exponent + 1;
+ }
+ this.mantissa = mantissa;
+ this.exponent = exponent;
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Basic object operations
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is BigDec))
+ return false;
+
+ return (this == (BigDec)obj);
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return this.mantissa.GetHashCode() * 13 + this.exponent.GetHashCode();
+ }
+
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return String.Format("{0}e{1}", this.mantissa.ToString(), this.exponent.ToString());
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Conversion operations
+
+ [Pure]
+ public BIM Floor(BIM? minimum, BIM? maximum) {
+ BIM n = this.mantissa;
+
+ if (this.exponent >= 0) {
+ int e = this.exponent;
+ while (e > 0 && (minimum == null || minimum <= n) && (maximum == null || n <= maximum)) {
+ n = n * ten;
+ e = e - 1;
+ }
+ }
+ else {
+ int e = -this.exponent;
+ while (e > 0 && !n.IsZero) {
+ n = n / ten;
+ e = e - 1;
+ }
+ }
+
+ if (minimum != null && n < minimum)
+ return (BIM)minimum;
+ else if (maximum != null && maximum < n)
+ return (BIM)maximum;
+ else
+ return n;
+ }
+
+ [Pure]
+ public String ToDecimalString(int maxDigits) {
+ string s = this.mantissa.ToString();
+ int digits = (this.mantissa >= 0) ? s.Length : s.Length - 1;
+ BIM max = BIM.Pow(10, maxDigits);
+ BIM min = -max;
+
+ if (this.exponent >= 0) {
+ if (maxDigits < digits || maxDigits - digits < this.exponent) {
+ return String.Format("{0}.0", (this.mantissa >= 0) ? max.ToString() : min.ToString());
+ }
+ else {
+ return String.Format("{0}{1}.0", s, new string('0', this.exponent));
+ }
+ }
+ else {
+ int exp = -this.exponent;
+
+ if (exp < digits) {
+ int intDigits = digits - exp;
+ if (maxDigits < intDigits) {
+ return String.Format("{0}.0", (this.mantissa >= 0) ? max.ToString() : min.ToString());
+ }
+ else {
+ int fracDigits = Math.Min(maxDigits, digits - intDigits);
+ return String.Format("{0}.{1}", s.Substring(0, intDigits), s.Substring(intDigits, fracDigits));
+ }
+ }
+ else {
+ int fracDigits = Math.Min(maxDigits, digits);
+ return String.Format("0.{0}{1}", new string('0', exp - fracDigits), s.Substring(0, fracDigits));
+ }
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Basic arithmetic operations
+
+ [Pure]
+ public BigDec Abs {
+ get {
+ return new BigDec(BIM.Abs(this.mantissa), this.exponent);
+ }
+ }
+
+ [Pure]
+ public BigDec Negate {
+ get {
+ return new BigDec(BIM.Negate(this.mantissa), this.exponent);
+ }
+ }
+
+ [Pure]
+ public static BigDec operator -(BigDec x) {
+ return x.Negate;
+ }
+
+ [Pure]
+ public static BigDec operator +(BigDec x, BigDec y) {
+ BIM m1 = x.mantissa;
+ int e1 = x.exponent;
+ BIM m2 = y.mantissa;
+ int e2 = y.exponent;
+ if (e2 < e1) {
+ m1 = y.mantissa;
+ e1 = y.exponent;
+ m2 = x.mantissa;
+ e2 = x.exponent;
+ }
+
+ while (e2 > e1) {
+ m2 = m2 * ten;
+ e2 = e2 - 1;
+ }
+
+ return new BigDec(m1 + m2, e1);
+ }
+
+ [Pure]
+ public static BigDec operator -(BigDec x, BigDec y) {
+ return x + y.Negate;
+ }
+
+ [Pure]
+ public static BigDec operator *(BigDec x, BigDec y) {
+ return new BigDec(x.mantissa * y.mantissa, x.exponent + y.exponent);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Some basic comparison operations
+
+ public bool IsPositive {
+ get {
+ return (this.mantissa > BIM.Zero);
+ }
+ }
+
+ public bool IsNegative {
+ get {
+ return (this.mantissa < BIM.Zero);
+ }
+ }
+
+ public bool IsZero {
+ get {
+ return this.mantissa.IsZero;
+ }
+ }
+
+ [Pure]
+ public int CompareTo(BigDec that) {
+ if (this.mantissa == that.mantissa && this.exponent == that.exponent) {
+ return 0;
+ }
+ else {
+ BigDec d = this - that;
+ return d.IsNegative ? -1 : 1;
+ }
+ }
+
+ [Pure]
+ public static bool operator ==(BigDec x, BigDec y) {
+ return x.CompareTo(y) == 0;
+ }
+
+ [Pure]
+ public static bool operator !=(BigDec x, BigDec y) {
+ return x.CompareTo(y) != 0;
+ }
+
+ [Pure]
+ public static bool operator <(BigDec x, BigDec y) {
+ return x.CompareTo(y) < 0;
+ }
+
+ [Pure]
+ public static bool operator >(BigDec x, BigDec y) {
+ return x.CompareTo(y) > 0;
+ }
+
+ [Pure]
+ public static bool operator <=(BigDec x, BigDec y) {
+ return x.CompareTo(y) <= 0;
+ }
+
+ [Pure]
+ public static bool operator >=(BigDec x, BigDec y) {
+ return x.CompareTo(y) >= 0;
+ }
+ }
+}
diff --git a/Source/Boogie.sln b/Source/Boogie.sln
index 1e733880..f3f068d7 100644
--- a/Source/Boogie.sln
+++ b/Source/Boogie.sln
@@ -1,12 +1,10 @@

-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Provers", "Provers", "{B758C1E3-824A-439F-AA2F-0BA1143E8C8D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoogieDriver", "BoogieDriver\BoogieDriver.csproj", "{DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Isabelle", "Provers\Isabelle\Isabelle.csproj", "{435D5BD0-6F62-49F8-BB24-33E2257519AD}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AbsInt", "AbsInt\AbsInt.csproj", "{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMTLib", "Provers\SMTLib\SMTLib.csproj", "{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}"
@@ -17,10 +15,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VCExpr", "VCExpr\VCExpr.csp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core\Core.csproj", "{B230A69C-C466-4065-B9C1-84D80E76D802}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Z3api", "Provers\Z3api\Z3api.csproj", "{966DD87B-A29D-4F3C-9406-F680A61DC0E0}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AIFramework", "AIFramework\AIFramework.csproj", "{39B0658D-C955-41C5-9A43-48C97A1EF5FD}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Graph", "Graph\Graph.csproj", "{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Basetypes", "Basetypes\Basetypes.csproj", "{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}"
@@ -35,6 +29,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParserHelper", "ParserHelpe
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Houdini", "Houdini\Houdini.csproj", "{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Predication", "Predication\Predication.csproj", "{AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Doomed", "Doomed\Doomed.csproj", "{884386A3-58E9-40BB-A273-B24976775553}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Checked|.NET = Checked|.NET
@@ -81,32 +79,6 @@ Global
{DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|x86.ActiveCfg = z3apidebug|x86
{DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|x86.Build.0 = z3apidebug|x86
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|x86.ActiveCfg = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|.NET.Build.0 = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|x86.ActiveCfg = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|.NET.ActiveCfg = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Any CPU.Build.0 = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|x86.ActiveCfg = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|.NET.ActiveCfg = Checked|Any CPU
{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -235,53 +207,6 @@ Global
{B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
{B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Checked|x86.ActiveCfg = Checked|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Debug|x86.ActiveCfg = Debug|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Release|.NET.ActiveCfg = Release|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Release|Any CPU.Build.0 = Release|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Release|x86.ActiveCfg = Release|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.z3apidebug|Mixed Platforms.ActiveCfg = z3apidebug|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.z3apidebug|Mixed Platforms.Build.0 = z3apidebug|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Checked|x86.ActiveCfg = Checked|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Debug|x86.ActiveCfg = Debug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Release|.NET.ActiveCfg = Release|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Release|Any CPU.Build.0 = Release|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Release|x86.ActiveCfg = Release|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|.NET.ActiveCfg = Checked|Any CPU
{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -456,13 +381,59 @@ Global
{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|x86.ActiveCfg = Release|Any CPU
{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|x86.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|.NET.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|Any CPU.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|Any CPU.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|Mixed Platforms.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|x86.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|.NET.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|x86.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|.NET.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|Any CPU.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|Any CPU.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|Mixed Platforms.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|x86.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|.NET.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|Any CPU.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|x86.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {435D5BD0-6F62-49F8-BB24-33E2257519AD} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
- {966DD87B-A29D-4F3C-9406-F680A61DC0E0} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
EndGlobalSection
EndGlobal
diff --git a/Source/BoogieDriver/BoogieDriver.cs b/Source/BoogieDriver/BoogieDriver.cs
index 1653b723..402b5c68 100644
--- a/Source/BoogieDriver/BoogieDriver.cs
+++ b/Source/BoogieDriver/BoogieDriver.cs
@@ -20,7 +20,6 @@ namespace Microsoft.Boogie {
using System.Diagnostics;
using System.Linq;
using VC;
- using AI = Microsoft.AbstractInterpretationFramework;
using BoogiePL = Microsoft.Boogie;
/*
@@ -583,25 +582,18 @@ namespace Microsoft.Boogie {
// ---------- Infer invariants --------------------------------------------------------
// Abstract interpretation -> Always use (at least) intervals, if not specified otherwise (e.g. with the "/noinfer" switch)
- if (CommandLineOptions.Clo.Ai.J_Intervals || CommandLineOptions.Clo.Ai.J_Trivial) {
- Microsoft.Boogie.AbstractInterpretation.NativeAbstractInterpretation.RunAbstractInterpretation(program);
- } else {
- Microsoft.Boogie.AbstractInterpretation.AbstractInterpretation.RunAbstractInterpretation(program);
+ if (CommandLineOptions.Clo.UseAbstractInterpretation) {
+ if (!CommandLineOptions.Clo.Ai.J_Intervals && !CommandLineOptions.Clo.Ai.J_Trivial) {
+ // use /infer:j as the default
+ CommandLineOptions.Clo.Ai.J_Intervals = true;
+ }
}
+ Microsoft.Boogie.AbstractInterpretation.NativeAbstractInterpretation.RunAbstractInterpretation(program);
if (CommandLineOptions.Clo.LoopUnrollCount != -1) {
program.UnrollLoops(CommandLineOptions.Clo.LoopUnrollCount);
}
- if (CommandLineOptions.Clo.DoPredication && CommandLineOptions.Clo.StratifiedInlining > 0) {
- BlockPredicator.Predicate(program, false, false);
- if (CommandLineOptions.Clo.PrintInstrumented) {
- using (TokenTextWriter writer = new TokenTextWriter(Console.Out)) {
- program.Emit(writer);
- }
- }
- }
-
Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo = null;
if (CommandLineOptions.Clo.ExtractLoops)
{
@@ -667,7 +659,7 @@ namespace Microsoft.Boogie {
try {
if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
vcgen = new DCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend);
- } else if(CommandLineOptions.Clo.StratifiedInlining > 0) {
+ } else if (CommandLineOptions.Clo.StratifiedInlining > 0) {
vcgen = new StratifiedVCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend);
} else {
vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend);
diff --git a/Source/BoogieDriver/BoogieDriver.csproj b/Source/BoogieDriver/BoogieDriver.csproj
index 57aeb4d9..36795a68 100644
--- a/Source/BoogieDriver/BoogieDriver.csproj
+++ b/Source/BoogieDriver/BoogieDriver.csproj
@@ -214,10 +214,6 @@
<Project>{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}</Project>
<Name>AbsInt</Name>
</ProjectReference>
- <ProjectReference Include="..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
<ProjectReference Include="..\Basetypes\Basetypes.csproj">
<Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
<Name>Basetypes</Name>
@@ -230,6 +226,10 @@
<Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
<Name>Core</Name>
</ProjectReference>
+ <ProjectReference Include="..\Doomed\Doomed.csproj">
+ <Project>{884386a3-58e9-40bb-a273-b24976775553}</Project>
+ <Name>Doomed</Name>
+ </ProjectReference>
<ProjectReference Include="..\Graph\Graph.csproj">
<Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
<Name>Graph</Name>
@@ -242,9 +242,9 @@
<Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
<Name>ParserHelper</Name>
</ProjectReference>
- <ProjectReference Include="..\Provers\Isabelle\Isabelle.csproj">
- <Project>{435D5BD0-6F62-49F8-BB24-33E2257519AD}</Project>
- <Name>Isabelle</Name>
+ <ProjectReference Include="..\Predication\Predication.csproj">
+ <Project>{afaa5ce1-c41b-44f0-88f8-fd8a43826d44}</Project>
+ <Name>Predication</Name>
</ProjectReference>
<ProjectReference Include="..\Provers\SMTLib\SMTLib.csproj">
<Project>{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}</Project>
diff --git a/Source/Core/Absy.cs b/Source/Core/Absy.cs
index 9df982d9..c8c052b7 100644
--- a/Source/Core/Absy.cs
+++ b/Source/Core/Absy.cs
@@ -11,56 +11,40 @@ namespace Microsoft.Boogie.AbstractInterpretation {
using System.Diagnostics.Contracts;
using System.Collections;
using System.Collections.Generic;
- using AI = Microsoft.AbstractInterpretationFramework;
public class CallSite {
public readonly Implementation/*!*/ Impl;
public readonly Block/*!*/ Block;
public readonly int Statement; // invariant: Block[Statement] is CallCmd
- public readonly AI.Lattice.Element/*!*/ KnownBeforeCall;
public readonly ProcedureSummaryEntry/*!*/ SummaryEntry;
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(Impl != null);
Contract.Invariant(Block != null);
- Contract.Invariant(KnownBeforeCall != null);
Contract.Invariant(SummaryEntry != null);
}
- public CallSite(Implementation impl, Block b, int stmt, AI.Lattice.Element e, ProcedureSummaryEntry summaryEntry) {
+ public CallSite(Implementation impl, Block b, int stmt, ProcedureSummaryEntry summaryEntry) {
Contract.Requires(summaryEntry != null);
- Contract.Requires(e != null);
Contract.Requires(b != null);
Contract.Requires(impl != null);
this.Impl = impl;
this.Block = b;
this.Statement = stmt;
- this.KnownBeforeCall = e;
this.SummaryEntry = summaryEntry;
}
}
public class ProcedureSummaryEntry {
- public AI.Lattice/*!*/ Lattice;
- public AI.Lattice.Element/*!*/ OnEntry;
- public AI.Lattice.Element/*!*/ OnExit;
public HashSet<CallSite>/*!*/ ReturnPoints; // whenever OnExit changes, we start analysis again at all the ReturnPoints
[ContractInvariantMethod]
void ObjectInvariant() {
- Contract.Invariant(Lattice != null);
- Contract.Invariant(OnEntry != null);
- Contract.Invariant(OnExit != null);
Contract.Invariant(ReturnPoints != null);
}
- public ProcedureSummaryEntry(AI.Lattice lattice, AI.Lattice.Element onEntry) {
- Contract.Requires(onEntry != null);
- Contract.Requires(lattice != null);
- this.Lattice = lattice;
- this.OnEntry = onEntry;
- this.OnExit = lattice.Bottom;
+ public ProcedureSummaryEntry() {
this.ReturnPoints = new HashSet<CallSite>();
// base();
}
@@ -93,8 +77,7 @@ namespace Microsoft.Boogie {
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using Microsoft.Boogie.AbstractInterpretation;
- using AI = Microsoft.AbstractInterpretationFramework;
- using Graphing;
+ using Microsoft.Boogie.GraphUtil;
using Set = GSet<object>;
[ContractClass(typeof(AbsyContracts))]
@@ -349,12 +332,6 @@ namespace Microsoft.Boogie {
}
}
- public void InstrumentWithInvariants() {
- foreach (Declaration d in this.TopLevelDeclarations) {
- d.InstrumentWithInvariants();
- }
- }
-
/// <summary>
/// Reset the abstract stated computed before
/// </summary>
@@ -1045,14 +1022,6 @@ namespace Microsoft.Boogie {
}
/// <summary>
- /// This method inserts the abstract-interpretation-inferred invariants
- /// as assume (or possibly assert) statements in the statement sequences of
- /// each block.
- /// </summary>
- public virtual void InstrumentWithInvariants() {
- }
-
- /// <summary>
/// Reset the abstract stated computed before
/// </summary>
public virtual void ResetAbstractInterpretationState() { /* does nothing */
@@ -1388,7 +1357,7 @@ namespace Microsoft.Boogie {
}
}
- public abstract class Variable : NamedDeclaration, AI.IVariable {
+ public abstract class Variable : NamedDeclaration {
public TypedIdent/*!*/ TypedIdent;
[ContractInvariantMethod]
void ObjectInvariant() {
@@ -1446,11 +1415,6 @@ namespace Microsoft.Boogie {
TypecheckAttributes(tc);
this.TypedIdent.Typecheck(tc);
}
- [Pure]
- public object DoVisit(AI.ExprVisitor visitor) {
- //Contract.Requires(visitor != null);
- return visitor.VisitVariable(this);
- }
}
public class VariableComparer : IComparer {
@@ -2354,12 +2318,6 @@ namespace Microsoft.Boogie {
for (int s = 0; s < this.Summary.Count; s++) {
ProcedureSummaryEntry/*!*/ entry = cce.NonNull(this.Summary[s]);
stream.Write(level + 1, "// ");
- Expr e;
- e = (Expr)entry.Lattice.ToPredicate(entry.OnEntry);
- e.Emit(stream);
- stream.Write(" ==> ");
- e = (Expr)entry.Lattice.ToPredicate(entry.OnExit);
- e.Emit(stream);
stream.WriteLine();
}
}
@@ -2862,53 +2820,6 @@ namespace Microsoft.Boogie {
}
/// <summary>
- /// Instrument the blocks with the inferred invariants
- /// </summary>
- public override void InstrumentWithInvariants() {
- foreach (Block b in this.Blocks) {
- if (b.Lattice != null) {
- Contract.Assert(b.PreInvariant != null); /* If the pre-abstract state is null, then something is wrong */
- Contract.Assert(b.PostInvariant != null); /* If the post-state is null, then something is wrong */
-
- bool instrumentEntry;
- bool instrumentExit;
- switch (CommandLineOptions.Clo.InstrumentInfer) {
- case CommandLineOptions.InstrumentationPlaces.Everywhere:
- instrumentEntry = true;
- instrumentExit = true;
- break;
- case CommandLineOptions.InstrumentationPlaces.LoopHeaders:
- instrumentEntry = b.widenBlock;
- instrumentExit = false;
- break;
- default: {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // unexpected InstrumentationPlaces value
- }
-
- if (instrumentEntry || instrumentExit) {
- CmdSeq newCommands = new CmdSeq();
- if (instrumentEntry) {
- Expr inv = (Expr)b.Lattice.ToPredicate(b.PreInvariant); /*b.PreInvariantBuckets.GetDisjunction(b.Lattice);*/
- var kv = new QKeyValue(Token.NoToken, "inferred", new List<object>(), null);
- PredicateCmd cmd = CommandLineOptions.Clo.InstrumentWithAsserts ? (PredicateCmd)new AssertCmd(Token.NoToken, inv, kv) : (PredicateCmd)new AssumeCmd(Token.NoToken, inv, kv);
- newCommands.Add(cmd);
- }
- newCommands.AddRange(b.Cmds);
- if (instrumentExit) {
- Expr inv = (Expr)b.Lattice.ToPredicate(b.PostInvariant);
- var kv = new QKeyValue(Token.NoToken, "inferred", new List<object>(), null);
- PredicateCmd cmd = CommandLineOptions.Clo.InstrumentWithAsserts ? (PredicateCmd)new AssertCmd(Token.NoToken, inv, kv) : (PredicateCmd)new AssumeCmd(Token.NoToken, inv, kv);
- newCommands.Add(cmd);
- }
- b.Cmds = newCommands;
- }
- }
- }
- }
-
- /// <summary>
/// Return a collection of blocks that are reachable from the block passed as a parameter.
/// The block must be defined in the current implementation
/// </summary>
@@ -3148,113 +3059,6 @@ namespace Microsoft.Boogie {
}
}
- /// <summary>
- /// Conceptually, a LatticeElementList is a infinite array indexed from 0,
- /// where some finite number of elements have a non-null value. All elements
- /// have type Lattice.Element.
- ///
- /// The Count property returns the first index above all non-null values.
- ///
- /// The [i] getter returns the element at position i, which may be null. The
- /// index i is not allowed to be negative.
- /// The [i] setter sets the element at position i. As a side effect, this
- /// operation may increase Count. The index i is not allowed to be negative.
- /// The right-hand value of the setter is not allowed to be null; that is,
- /// null can occur in the list only as an "unused" element.
- /// </summary>
- public class LatticeElementList : ArrayList {
- public new /*Maybe null*/ AI.Lattice.Element this[int i] {
- get {
- if (i < Count) {
- return (AI.Lattice.Element)base[i];
- } else {
- return null;
- }
- }
- set {
- System.Diagnostics.Debug.Assert(value != null);
- while (Count <= i) {
- Add(null);
- }
- base[i] = value;
- }
- }
- /// <summary>
- /// Returns the disjunction of (the expression formed from) the
- /// non-null lattice elements in the list. The expressions are
- /// formed according to the given "lattice", which is assumed to
- /// be the lattice of the lattice elements stored in the list.
- /// </summary>
- /// <param name="lattice"></param>
- /// <returns></returns>
- public Expr GetDisjunction(AI.Lattice lattice) {
- Contract.Requires(lattice != null);
- Expr disjunction = null;
- foreach (AI.Lattice.Element el in this) {
- if (el != null) {
- Expr e = (Expr)lattice.ToPredicate(el);
- if (disjunction == null) {
- disjunction = e;
- } else {
- disjunction = Expr.Or(disjunction, e);
- }
- }
- }
- if (disjunction == null) {
- return Expr.False;
- } else {
- return disjunction;
- }
- }
- }
-
- public abstract class BoogieFactory {
- public static Expr IExpr2Expr(AI.IExpr e) {
- Contract.Requires(e != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Variable v = e as Variable;
- if (v != null) {
- return new IdentifierExpr(Token.NoToken, v);
- } else if (e is AI.IVariable) { // but not a Variable
- return new AIVariableExpr(Token.NoToken, (AI.IVariable)e);
- } else if (e is IdentifierExpr.ConstantFunApp) {
- return ((IdentifierExpr.ConstantFunApp)e).IdentifierExpr;
- } else if (e is QuantifierExpr.AIQuantifier) {
- return ((QuantifierExpr.AIQuantifier)e).arg.RealQuantifier;
- } else {
- return (Expr)e;
- }
- }
- public static ExprSeq IExprArray2ExprSeq(IList/*<AI.IExpr!>*/ a) {
- Contract.Requires(a != null);
- Contract.Ensures(Contract.Result<ExprSeq>() != null);
- Expr[] e = new Expr[a.Count];
- int i = 0;
- foreach (AI.IExpr/*!*/ aei in a) {
- Contract.Assert(aei != null);
- e[i] = IExpr2Expr(aei);
- i++;
- }
- return new ExprSeq(e);
- }
-
- // Convert a Boogie type into an AIType if possible. This should be
- // extended when AIFramework gets more types.
- public static AI.AIType Type2AIType(Type t) {
- Contract.Requires(t != null);
- Contract.Ensures(Contract.Result<AI.AIType>() != null);
- // if (t.IsRef)
- // return AI.Ref.Type;
- // else
- if (t.IsInt)
- return AI.Int.Type;
- // else if (t.IsName) PR: how to handle this case?
- // return AI.FieldName.Type;
- else
- return AI.Value.Type;
- }
- }
-
#region Generic Sequences
//---------------------------------------------------------------------
// Generic Sequences
diff --git a/Source/Core/AbsyCmd.cs b/Source/Core/AbsyCmd.cs
index c6b66585..607848ed 100644
--- a/Source/Core/AbsyCmd.cs
+++ b/Source/Core/AbsyCmd.cs
@@ -13,7 +13,6 @@ namespace Microsoft.Boogie {
using System.Diagnostics;
using System.Collections.Generic;
using Microsoft.Boogie.AbstractInterpretation;
- using AI = Microsoft.AbstractInterpretationFramework;
using System.Diagnostics.Contracts;
using Set = GSet<object>;
@@ -818,13 +817,6 @@ namespace Microsoft.Boogie {
public bool widenBlock;
public int iterations; // Count the number of time we visited the block during fixpoint computation. Used to decide if we widen or not
- // Block-specific invariants...
- public AI.Lattice Lattice; // The lattice used for the analysis of this block
- public AI.Lattice.Element PreInvariant; // The initial abstract states for this block
- public AI.Lattice.Element PostInvariant; // The exit abstract states for this block
- // KRML: We want to include the following invariant, but at the moment, doing so causes a run-time error (something about committed):
- //invariant ;
-
// VC generation and SCC computation
public BlockSeq/*!*/ Predecessors;
@@ -837,7 +829,6 @@ namespace Microsoft.Boogie {
Contract.Invariant(Label != null);
Contract.Invariant(Cmds != null);
Contract.Invariant(cce.NonNullElements(liveVarsBefore, true));
- Contract.Invariant((PreInvariant != null) == (PostInvariant != null));
}
public bool IsLive(Variable v) {
@@ -860,8 +851,6 @@ namespace Microsoft.Boogie {
this.Label = label;
this.Cmds = cmds;
this.TransferCmd = transferCmd;
- this.PreInvariant = null;
- this.PostInvariant = null;
this.Predecessors = new BlockSeq();
this.liveVarsBefore = null;
this.TraversingStatus = VisitState.ToVisit;
@@ -920,9 +909,6 @@ namespace Microsoft.Boogie {
// this.currentlyTraversed = false;
this.TraversingStatus = VisitState.ToVisit;
this.iterations = 0;
- this.Lattice = null;
- this.PreInvariant = null;
- this.PostInvariant = null;
}
[Pure]
diff --git a/Source/Core/AbsyExpr.cs b/Source/Core/AbsyExpr.cs
index e274fcc3..ff84b501 100644
--- a/Source/Core/AbsyExpr.cs
+++ b/Source/Core/AbsyExpr.cs
@@ -13,8 +13,6 @@ namespace Microsoft.Boogie {
using System.Diagnostics;
using System.Collections.Generic;
using Microsoft.Boogie.AbstractInterpretation;
- using AI = Microsoft.AbstractInterpretationFramework;
- using Microsoft.AbstractInterpretationFramework;//DANGER: Added?
using System.Diagnostics.Contracts;
using Microsoft.Basetypes;
@@ -252,6 +250,18 @@ namespace Microsoft.Boogie {
Contract.Ensures(Contract.Result<NAryExpr>() != null);
return Binary(BinaryOperator.Opcode.Mod, e1, e2);
}
+ public static NAryExpr RealDiv(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.RealDiv, e1, e2);
+ }
+ public static NAryExpr Pow(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Pow, e1, e2);
+ }
public static NAryExpr Subtype(Expr e1, Expr e2) {
Contract.Requires(e2 != null);
Contract.Requires(e1 != null);
@@ -285,6 +295,10 @@ namespace Microsoft.Boogie {
Contract.Ensures(Contract.Result<LiteralExpr>() != null);
return new LiteralExpr(Token.NoToken, value);
}
+ public static LiteralExpr Literal(BigDec value) {
+ Contract.Ensures(Contract.Result<LiteralExpr>() != null);
+ return new LiteralExpr(Token.NoToken, value);
+ }
private static LiteralExpr/*!*/ true_ = Literal(true);
public static LiteralExpr/*!*/ True {
@@ -379,21 +393,6 @@ namespace Microsoft.Boogie {
args.Add(subexpr);
return new NAryExpr(x, new TypeCoercion(x, type), args);
}
-
-
- /// <summary>
- /// This property returns a representation for the expression suitable for use
- /// by the AIFramework. Usually, the property just returns "this", but not
- /// every Expr is an AI.IExpr (besides, AI.IExpr is to be thought of as an
- /// abstract interface--any class that implements AI.IExpr is supposed to
- /// implement some proper subinterface of AI.IExpr).
- /// The converse operations of this property are found in AbsInt\ExprFactories.ssc.
- /// </summary>
- public abstract AI.IExpr/*!*/ IExpr {
- [Peer]
- get;
- }
-
}
[ContractClassFor(typeof(Expr))]
public abstract class ExprContracts : Expr {
@@ -415,17 +414,10 @@ namespace Microsoft.Boogie {
throw new NotImplementedException();
}
}
- public override Microsoft.AbstractInterpretationFramework.IExpr IExpr {
- get {
- Contract.Ensures(Contract.Result<Microsoft.AbstractInterpretationFramework.IExpr>() != null);
-
- throw new NotImplementedException();
- }
- }
}
- public class LiteralExpr : Expr, AI.IFunApp {
- public readonly object/*!*/ Val; // false, true, a BigNum, or a BvConst
+ public class LiteralExpr : Expr {
+ public readonly object/*!*/ Val; // false, true, a BigNum, a BigDec, or a BvConst
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(Val != null);
@@ -442,6 +434,7 @@ namespace Microsoft.Boogie {
Val = b;
Type = Type.Bool;
}
+
/// <summary>
/// Creates a literal expression for the integer value "v".
/// </summary>
@@ -455,6 +448,18 @@ namespace Microsoft.Boogie {
}
/// <summary>
+ /// Creates a literal expression for the real value "v".
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="v"></param>
+ public LiteralExpr(IToken/*!*/ tok, BigDec v)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Val = v;
+ Type = Type.Real;
+ }
+
+ /// <summary>
/// Creates a literal expression for the bitvector value "v".
/// </summary>
public LiteralExpr(IToken/*!*/ tok, BigNum v, int b)
@@ -511,6 +516,8 @@ namespace Microsoft.Boogie {
return Type.Bool;
} else if (Val is BigNum) {
return Type.Int;
+ } else if (Val is BigDec) {
+ return Type.Real;
} else if (Val is BvConst) {
return Type.GetBvType(((BvConst)Val).Bits);
} else {
@@ -532,12 +539,6 @@ namespace Microsoft.Boogie {
return Val is bool && ((bool)Val) == true;
}
}
- public override AI.IExpr/*!*/ IExpr {
- get {
- Contract.Ensures(Contract.Result<AI.IExpr>() != null);
- return this;
- }
- }
// should be eliminated after converting everything to BigNums
private int asInt {
@@ -559,76 +560,31 @@ namespace Microsoft.Boogie {
}
}
- public bool isBool {
+ public bool isBigDec {
get {
- return Val is bool;
+ return Val is BigDec;
}
}
- public bool asBool {
+ public BigDec asBigDec {
get {
- Contract.Assert(isBool);
- return (bool)cce.NonNull(Val);
+ Contract.Assert(isBigDec);
+ return (BigDec)cce.NonNull(Val);
}
}
- public AI.IFunctionSymbol/*!*/ FunctionSymbol {
+ public bool isBool {
get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
-
- if (Val is bool) {
- if ((bool)Val) {
- return AI.Prop.True;
- } else {
- return AI.Prop.False;
- }
- } else if (Val is BigNum) {
- return AI.Int.Const((BigNum)Val);
- } else if (Val is BvConst) {
- return AI.Bv.Const(((BvConst)Val).Value, ((BvConst)Val).Bits);
- } else {
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // like, where did this value come from?!
- }
+ return Val is bool;
}
}
- public IList/*<AI.IExpr!>*//*!*/ Arguments {
- get {
- Contract.Ensures(Contract.Result<IList>() != null);
- return ArrayList.ReadOnly(new AI.IExpr[0]);
- }
- }
- public Microsoft.AbstractInterpretationFramework.IFunApp CloneWithArguments(IList/*<AI.IExpr!>*/ args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<Microsoft.AbstractInterpretationFramework.IFunApp>() != null);
- Contract.Assert(args.Count == 0);
- return this;
- }
- public AI.AIType/*!*/ AIType {
+ public bool asBool {
get {
- Contract.Requires(AIType != null);
- if (Val is bool) {
- return AI.Prop.Type;
- } else if (Val is BigNum) {
- return AI.Int.Type;
- } else if (Val is BvConst) {
- return AI.Bv.Type;
- } else {
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // like, where did this value come from?!
- }
+ Contract.Assert(isBool);
+ return (bool)cce.NonNull(Val);
}
}
- [Pure]
- public object DoVisit(AI.ExprVisitor visitor) {
- //Contract.Requires(visitor != null);
- return visitor.VisitFunApp(this);
- }
public override Absy StdDispatch(StandardVisitor visitor) {
//Contract.Requires(visitor != null);
@@ -688,86 +644,6 @@ namespace Microsoft.Boogie {
}
}
- public class AIVariableExpr : Expr {
-
- public string Name; // identifier symbol
- public AI.IVariable/*!*/ Decl; // identifier declaration
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Decl != null);
- }
-
-
- /// <summary>
- /// Creates an unresolved identifier expression.
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="name"></param>
- public AIVariableExpr(IToken/*!*/ tok, AI.IVariable/*!*/ var)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(var != null);
- Name = var.ToString();
- Decl = var;
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is AIVariableExpr))
- return false;
-
- AIVariableExpr other = (AIVariableExpr)obj;
- return object.Equals(this.Name, other.Name) && object.Equals(this.Decl, other.Decl);
- }
- [Pure]
- public override int GetHashCode() {
- int h = this.Name == null ? 0 : this.Name.GetHashCode();
- h ^= this.Decl == null ? 0 : this.Decl.GetHashCode();
- return h;
- }
- public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
- stream.Write("{0}^^", this.Decl == null ? "NoDecl" : "h" + this.Decl.GetHashCode());
- }
- stream.Write(this, "{0}", this.Name);
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- }
- public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
- //Contract.Requires(freeVars != null);
- if (Decl is Variable) {
- freeVars.Add((Variable)Decl);
- }
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- throw new System.NotImplementedException();
- }
- public override Type/*!*/ ShallowType {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- throw new System.NotImplementedException();
- }
- }
- public override AI.IExpr/*!*/ IExpr {
- get {
- Contract.Ensures(Contract.Result<AI.IExpr>() != null);
-
- return Decl;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitAIVariableExpr(this);
- }
- }
-
public class IdentifierExpr : Expr {
public string/*!*/ Name; // identifier symbol
public Variable Decl; // identifier declaration
@@ -894,12 +770,11 @@ namespace Microsoft.Boogie {
}
}
- public sealed class ConstantFunApp : AI.IFunApp {
+ public sealed class ConstantFunApp {
private IdentifierExpr/*!*/ identifierExpr;
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(identifierExpr != null);
- Contract.Invariant(symbol != null);
Contract.Invariant(emptyArgs != null);
}
@@ -910,14 +785,6 @@ namespace Microsoft.Boogie {
}
}
- private AI.IFunctionSymbol/*!*/ symbol;
- public AI.IFunctionSymbol/*!*/ FunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
- return symbol;
- }
- }
-
private static IList/*!*/ emptyArgs = ArrayList.ReadOnly(cce.NonNull((IList/*!*/)new ArrayList()));
public IList/*!*/ Arguments {
get {
@@ -926,44 +793,14 @@ namespace Microsoft.Boogie {
}
}
- public AI.IFunApp CloneWithArguments(IList newargs) {
- //Contract.Requires(newargs != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- return this;
- }
-
- [Pure]
- public object DoVisit(AI.ExprVisitor visitor) {
- //Contract.Requires(visitor != null);
- return visitor.VisitFunApp(this);
- }
-
public ConstantFunApp(IdentifierExpr ie, Constant c) {
Contract.Requires(c != null);
Contract.Requires(ie != null);
this.identifierExpr = ie;
- this.symbol =
- new AI.NamedSymbol(c.TypedIdent.Name, BoogieFactory.Type2AIType(c.TypedIdent.Type));
// base();
}
}
- private AI.IExpr iexprCache = null;
- public override AI.IExpr/*!*/ IExpr {
- get {
- Contract.Ensures(Contract.Result<IExpr>() != null);
-
- if (iexprCache == null) {
- if (Decl is Constant)
- iexprCache = new ConstantFunApp(this, (Constant)Decl);
- else {
- Contract.Assume(this.Decl != null);
- iexprCache = Decl;
- }
- }
- return iexprCache;
- }
- }
public override Absy StdDispatch(StandardVisitor visitor) {
//Contract.Requires(visitor != null);
@@ -972,7 +809,7 @@ namespace Microsoft.Boogie {
}
}
- public class OldExpr : Expr, AI.IFunApp // HACK
+ public class OldExpr : Expr
{
public Expr/*!*/ Expr;
[ContractInvariantMethod]
@@ -1030,67 +867,6 @@ namespace Microsoft.Boogie {
return Expr.ShallowType;
}
}
- public override AI.IExpr/*!*/ IExpr {
- get {
- Contract.Ensures(Contract.Result<IExpr>() != null);
-
- // Put back these lines when "HACK" removed
- // // An Old expression has no AI.IExpr representation
- // {Contract.Assert(false);throw new cce.UnreachableException();}
- return this; // HACK
- }
- }
- [Pure]
- public object DoVisit(AI.ExprVisitor visitor) {
- //Contract.Requires(visitor != null);
- return visitor.VisitFunApp(this);
- }
- public AI.IFunApp CloneWithArguments(IList/*<IExpr!>*/ args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- Contract.Assume(args.Count == 1);
- AI.IExpr/*!*/ iexpr = (AI.IExpr)cce.NonNull(args[0]);
- return new OldExpr(Token.NoToken, BoogieFactory.IExpr2Expr(iexpr));
- }
- private IList/*?*/ argCache = null;
- public IList/*<IExpr!*//*!*/ Arguments {
-
- get {
- Contract.Ensures(Contract.Result<IList>() != null);
-
- if (argCache == null) {
- IList l = new ArrayList(1);
- l.Add(Expr.IExpr);
- argCache = ArrayList.ReadOnly(l);
- }
- return argCache;
- }
- }
- private sealed class OldFunctionSymbol : AI.IFunctionSymbol {
- private static readonly AI.AIType/*!*/ aitype = new AI.FunctionType(AI.Value.Type, AI.Value.Type);
-
- public AI.AIType/*!*/ AIType {
- get {
- Contract.Ensures(Contract.Result<AIType>() != null);
- return aitype;
- }
- }
- private OldFunctionSymbol() {
- }
- internal static readonly OldFunctionSymbol/*!*/ Sym = new OldFunctionSymbol();
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return "old";
- }
- }
- public AI.IFunctionSymbol/*!*/ FunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
- return OldFunctionSymbol.Sym;
- }
- }
public override Absy StdDispatch(StandardVisitor visitor) {
//Contract.Requires(visitor != null);
@@ -1106,6 +882,7 @@ namespace Microsoft.Boogie {
T Visit(MapSelect/*!*/ mapSelect);
T Visit(MapStore/*!*/ mapStore);
T Visit(TypeCoercion/*!*/ typeCoercion);
+ T Visit(ArithmeticCoercion/*!*/ arithCoercion);
T Visit(IfThenElse/*!*/ ifThenElse);
}
[ContractClassFor(typeof(IAppliableVisitor<>))]
@@ -1143,6 +920,11 @@ namespace Microsoft.Boogie {
throw new NotImplementedException();
}
+ public T Visit(ArithmeticCoercion arithCoercion) {
+ Contract.Requires(arithCoercion != null);
+ throw new NotImplementedException();
+ }
+
public T Visit(IfThenElse ifThenElse) {
Contract.Requires(ifThenElse != null);
throw new NotImplementedException();
@@ -1198,10 +980,6 @@ namespace Microsoft.Boogie {
/// </summary>
Type/*!*/ ShallowType(ExprSeq/*!*/ args);
- AI.IFunctionSymbol/*!*/ AIFunctionSymbol {
- get;
- }
-
T Dispatch<T>(IAppliableVisitor<T>/*!*/ visitor);
}
[ContractClassFor(typeof(IAppliable))]
@@ -1250,13 +1028,6 @@ namespace Microsoft.Boogie {
throw new NotImplementedException();
}
- public IFunctionSymbol AIFunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
- throw new NotImplementedException();
- }
- }
-
public T Dispatch<T>(IAppliableVisitor<T> visitor) {
Contract.Requires(visitor != null);
throw new NotImplementedException();
@@ -1291,6 +1062,7 @@ namespace Microsoft.Boogie {
}
public enum Opcode {
+ Neg,
Not
};
private Opcode op;
@@ -1326,6 +1098,8 @@ namespace Microsoft.Boogie {
Contract.Ensures(Contract.Result<string>() != null);
switch (this.op) {
+ case Opcode.Neg:
+ return "-";
case Opcode.Not:
return "!";
}
@@ -1334,26 +1108,13 @@ namespace Microsoft.Boogie {
}
}
- public AI.IFunctionSymbol/*!*/ AIFunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
-
- switch (this.op) {
- case Opcode.Not:
- return AI.Prop.Not;
- }
- System.Diagnostics.Debug.Fail("unknown unary operator: " + op.ToString());
- throw new Exception();
- }
- }
-
public void Emit(ExprSeq args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
//Contract.Requires(stream != null);
//Contract.Requires(args != null);
stream.SetToken(ref this.tok);
Contract.Assert(args.Length == 1);
// determine if parens are needed
- int opBindingStrength = 0x60;
+ int opBindingStrength = 0x70;
bool parensNeeded = opBindingStrength < contextBindingStrength ||
(fragileContext && opBindingStrength == contextBindingStrength);
@@ -1391,6 +1152,14 @@ namespace Microsoft.Boogie {
tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
Type arg0type = cce.NonNull(cce.NonNull(args[0]).Type);
switch (this.op) {
+ case Opcode.Neg:
+ if (arg0type.Unify(Type.Int)) {
+ return Type.Int;
+ }
+ if (arg0type.Unify(Type.Real)) {
+ return Type.Real;
+ }
+ goto BAD_TYPE;
case Opcode.Not:
if (arg0type.Unify(Type.Bool)) {
return Type.Bool;
@@ -1411,6 +1180,8 @@ namespace Microsoft.Boogie {
//Contract.Requires(args != null);
Contract.Ensures(Contract.Result<Type>() != null);
switch (this.op) {
+ case Opcode.Neg:
+ return cce.NonNull(cce.NonNull(args[0]).Type);
case Opcode.Not:
return Type.Bool;
default: {
@@ -1425,6 +1196,14 @@ namespace Microsoft.Boogie {
return null;
}
switch (this.op) {
+ case Opcode.Neg:
+ if (argument is BigNum) {
+ return -((BigNum)argument);
+ }
+ if (argument is BigDec) {
+ return -((BigDec)argument);
+ }
+ break;
case Opcode.Not:
if (argument is bool) {
return !((bool)argument);
@@ -1453,6 +1232,8 @@ namespace Microsoft.Boogie {
Mul,
Div,
Mod,
+ RealDiv,
+ Pow,
Eq,
Neq,
Gt,
@@ -1506,9 +1287,13 @@ namespace Microsoft.Boogie {
case Opcode.Mul:
return "*";
case Opcode.Div:
- return "/";
+ return "div";
case Opcode.Mod:
- return "%";
+ return "mod";
+ case Opcode.RealDiv:
+ return "/";
+ case Opcode.Pow:
+ return "**";
case Opcode.Eq:
return "==";
case Opcode.Neq:
@@ -1537,50 +1322,6 @@ namespace Microsoft.Boogie {
}
}
- public AI.IFunctionSymbol/*!*/ AIFunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
-
- switch (this.op) {
-
- case Opcode.Add:
- return AI.Int.Add;
- case Opcode.Sub:
- return AI.Int.Sub;
- case Opcode.Mul:
- return AI.Int.Mul;
- case Opcode.Div:
- return AI.Int.Div;
- case Opcode.Mod:
- return AI.Int.Mod;
- case Opcode.Eq:
- return AI.Value.Eq;
- case Opcode.Neq:
- return AI.Value.Neq;
- case Opcode.Gt:
- return AI.Int.Greater;
- case Opcode.Ge:
- return AI.Int.AtLeast;
- case Opcode.Lt:
- return AI.Int.Less;
- case Opcode.Le:
- return AI.Int.AtMost;
- case Opcode.And:
- return AI.Prop.And;
- case Opcode.Or:
- return AI.Prop.Or;
- case Opcode.Imp:
- return AI.Prop.Implies;
- case Opcode.Iff:
- return AI.Value.Eq;
- case Opcode.Subtype:
- return AI.Value.Subtype;
- }
- System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
- throw new Exception();
- }
- }
-
public void Emit(ExprSeq args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
//Contract.Requires(stream != null);
//Contract.Requires(args != null);
@@ -1609,6 +1350,14 @@ namespace Microsoft.Boogie {
opBindingStrength = 0x50;
fragileRightContext = true;
break;
+ case Opcode.RealDiv:
+ opBindingStrength = 0x50;
+ fragileRightContext = true;
+ break;
+ case Opcode.Pow:
+ opBindingStrength = 0x60;
+ fragileRightContext = true;
+ break;
case Opcode.Eq:
case Opcode.Neq:
case Opcode.Gt:
@@ -1662,6 +1411,8 @@ namespace Microsoft.Boogie {
case Opcode.Mul:
case Opcode.Div:
case Opcode.Mod:
+ case Opcode.RealDiv:
+ case Opcode.Pow:
case Opcode.Neq: // Neq is allowed, but not Eq
case Opcode.Subtype:
// These are fine
@@ -1713,12 +1464,30 @@ namespace Microsoft.Boogie {
case Opcode.Add:
case Opcode.Sub:
case Opcode.Mul:
+ if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
+ return Type.Int;
+ }
+ if (arg0type.Unify(Type.Real) && arg1type.Unify(Type.Real)) {
+ return Type.Real;
+ }
+ goto BAD_TYPE;
case Opcode.Div:
case Opcode.Mod:
if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
return Type.Int;
}
goto BAD_TYPE;
+ case Opcode.RealDiv:
+ if ((arg0type.Unify(Type.Int) || arg0type.Unify(Type.Real)) &&
+ (arg1type.Unify(Type.Int) || arg1type.Unify(Type.Real))) {
+ return Type.Real;
+ }
+ goto BAD_TYPE;
+ case Opcode.Pow:
+ if (arg0type.Unify(Type.Real) && arg1type.Unify(Type.Real)) {
+ return Type.Real;
+ }
+ goto BAD_TYPE;
case Opcode.Eq:
case Opcode.Neq:
// Comparison is allowed if the argument types are unifiable
@@ -1742,6 +1511,9 @@ namespace Microsoft.Boogie {
if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
return Type.Bool;
}
+ if (arg0type.Unify(Type.Real) && arg1type.Unify(Type.Real)) {
+ return Type.Bool;
+ }
goto BAD_TYPE;
case Opcode.And:
case Opcode.Or:
@@ -1776,10 +1548,16 @@ namespace Microsoft.Boogie {
case Opcode.Add:
case Opcode.Sub:
case Opcode.Mul:
+ return cce.NonNull(args[0]).ShallowType;
+
case Opcode.Div:
case Opcode.Mod:
return Type.Int;
+ case Opcode.RealDiv:
+ case Opcode.Pow:
+ return Type.Real;
+
case Opcode.Eq:
case Opcode.Neq:
case Opcode.Gt:
@@ -1836,16 +1614,25 @@ namespace Microsoft.Boogie {
if (e1 is BigNum && e2 is BigNum) {
return ((BigNum)e1) + ((BigNum)e2);
}
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) + ((BigDec)e2);
+ }
break;
case Opcode.Sub:
if (e1 is BigNum && e2 is BigNum) {
return ((BigNum)e1) - ((BigNum)e2);
}
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) - ((BigDec)e2);
+ }
break;
case Opcode.Mul:
if (e1 is BigNum && e2 is BigNum) {
return ((BigNum)e1) * ((BigNum)e2);
}
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) * ((BigDec)e2);
+ }
break;
case Opcode.Div:
if (e1 is BigNum && e2 is BigNum) {
@@ -1857,25 +1644,43 @@ namespace Microsoft.Boogie {
return /* TODO: right semantics? */ ((BigNum)e1) % ((BigNum)e2);
}
break;
+ case Opcode.RealDiv:
+ // TODO: add partial evaluation fro real division
+ break;
+ case Opcode.Pow:
+ // TODO: add partial evaluation fro real exponentiation
+ break;
case Opcode.Lt:
if (e1 is BigNum && e2 is BigNum) {
return ((BigNum)e1) < ((BigNum)e2);
}
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) < ((BigDec)e2);
+ }
break;
case Opcode.Le:
if (e1 is BigNum && e2 is BigNum) {
return ((BigNum)e1) <= ((BigNum)e2);
}
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) <= ((BigDec)e2);
+ }
break;
case Opcode.Gt:
if (e1 is BigNum && e2 is BigNum) {
return ((BigNum)e1) > ((BigNum)e2);
}
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) > ((BigDec)e2);
+ }
break;
case Opcode.Ge:
if (e1 is BigNum && e2 is BigNum) {
return ((BigNum)e1) >= ((BigNum)e2);
}
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) >= ((BigDec)e2);
+ }
break;
case Opcode.And:
@@ -1917,7 +1722,7 @@ namespace Microsoft.Boogie {
}
- public class FunctionCall : IAppliable, AI.IFunctionSymbol {
+ public class FunctionCall : IAppliable {
private IdentifierExpr/*!*/ name;
public Function Func;
public FunctionCall(IdentifierExpr name) {
@@ -1940,25 +1745,6 @@ namespace Microsoft.Boogie {
Contract.Invariant(name != null);
}
- public FunctionCall createUnresolvedCopy()
- {
- return new FunctionCall(new IdentifierExpr(name.tok, name.Name, name.Type));
- }
-
- public AI.IFunctionSymbol/*!*/ AIFunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
-
- if (name.Name == "$typeof") {
- return AI.Value.Typeof;
- } else if (name.Name == "$allocated") {
- return AI.FieldName.Allocated;
- } else {
- return this;
- }
- }
- }
-
[Pure]
public override string ToString() {
Contract.Ensures(Contract.Result<string>() != null);
@@ -1977,15 +1763,6 @@ namespace Microsoft.Boogie {
return Func.GetHashCode();
}
- public AI.AIType/*!*/ AIType {
- get {
- Contract.Ensures(Contract.Result<AIType>() != null);
-
- Contract.Assume(this.Func != null);
- return AI.Value.FunctionType(this.Func.InParams.Length);
- }
- }
-
virtual public void Emit(ExprSeq args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
//Contract.Requires(stream != null);
//Contract.Requires(args != null);
@@ -2088,7 +1865,7 @@ namespace Microsoft.Boogie {
stream.SetToken(ref this.tok);
Contract.Assert(args.Length == 1);
// determine if parens are needed
- int opBindingStrength = 0x70;
+ int opBindingStrength = 0x80;
bool parensNeeded = opBindingStrength < contextBindingStrength ||
(fragileContext && opBindingStrength == contextBindingStrength);
@@ -2139,24 +1916,123 @@ namespace Microsoft.Boogie {
return this.Type;
}
- public AI.IFunctionSymbol/*!*/ AIFunctionSymbol {
+ public T Dispatch<T>(IAppliableVisitor<T> visitor) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this);
+ }
+
+ }
+
+ public class ArithmeticCoercion : IAppliable {
+ public enum CoercionType {
+ ToInt,
+ ToReal
+ }
+
+ private IToken/*!*/ tok;
+ public readonly CoercionType Coercion;
+ private readonly string name;
+ private readonly Type type;
+ private readonly Type argType;
+ private readonly int hashCode;
+
+ public ArithmeticCoercion(IToken tok, CoercionType coercion) {
+ this.tok = tok;
+ this.Coercion = coercion;
+
+ switch (coercion) {
+ case CoercionType.ToInt:
+ this.name = "int";
+ this.type = Type.Int;
+ this.argType = Type.Real;
+ this.hashCode = 1;
+ break;
+ case CoercionType.ToReal:
+ this.name = "real";
+ this.type = Type.Real;
+ this.argType = Type.Int;
+ this.hashCode = 2;
+ break;
+ default:
+ Contract.Assert(false);
+ break;
+ }
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return this.name;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other) {
+ ArithmeticCoercion ac = other as ArithmeticCoercion;
+ return ac != null && this.Coercion == ac.Coercion;
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return this.hashCode;
+ }
+
+ public string/*!*/ FunctionName {
get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
+ return this.name;
+ }
+ }
- // not really clear what should be returned here ...
- // should the operation be completely invisible for the abstract interpretation?
- return AI.Heap.UnsupportedHeapOp;
+ public int ArgumentCount {
+ get {
+ return 1;
}
}
- public T Dispatch<T>(IAppliableVisitor<T> visitor) {
+ virtual public void Emit(ExprSeq args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ //Contract.Requires(args != null);
+ stream.Write(this.name);
+ stream.Write("(");
+ args.Emit(stream);
+ stream.Write(")");
+ }
+
+ public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
+ //Contract.Requires(subjectForErrorReporting != null);
+ //Contract.Requires(rc != null);
+ }
+
+ public virtual Type Typecheck(ref ExprSeq args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ //Contract.Requires(args != null);
+ Contract.Ensures(args != null);
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+
+ Contract.Assert(args.Length == 1);
+
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+
+ if (!cce.NonNull(cce.NonNull(args[0]).Type).Unify(argType)) {
+ tc.Error(this.tok, "argument type {0} does not match expected type {1}", cce.NonNull(args[0]).Type, this.argType);
+ }
+
+ return this.type;
+ }
+
+ public Type ShallowType(ExprSeq args) {
+ //Contract.Requires(args != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this.type;
+ }
+
+ public virtual T Dispatch<T>(IAppliableVisitor<T> visitor) {
//Contract.Requires(visitor != null);
return visitor.Visit(this);
}
-
}
- public class NAryExpr : Expr, AI.IFunApp {
+ public class NAryExpr : Expr {
[Additive]
[Peer]
public IAppliable/*!*/ Fun;
@@ -2264,44 +2140,6 @@ namespace Microsoft.Boogie {
}
}
- public override AI.IExpr/*!*/ IExpr {
- get {
- Contract.Ensures(Contract.Result<IExpr>() != null);
-
- return this;
- }
- }
- public AI.IFunctionSymbol/*!*/ FunctionSymbol {
- get {
-
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
-
- return Fun.AIFunctionSymbol;
- }
- }
- public IList/*<AI.IExpr!>*//*!*/ Arguments {
- get {
- Contract.Ensures(Contract.Result<IList>() != null);
-
- AI.IExpr[] a = new AI.IExpr[Args.Length];
- for (int i = 0; i < Args.Length; i++) {
- a[i] = cce.NonNull(Args[i]).IExpr;
- }
- return ArrayList.ReadOnly(a);
- }
- }
- public AI.IFunApp CloneWithArguments(IList/*<AI.IExpr!>*/ args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- return new NAryExpr(this.tok, this.Fun, BoogieFactory.IExprArray2ExprSeq(args));
- }
-
- [Pure]
- public object DoVisit(AI.ExprVisitor visitor) {
- //Contract.Requires(visitor != null);
- return visitor.VisitFunApp(this);
- }
-
public override Absy StdDispatch(StandardVisitor visitor) {
//Contract.Requires(visitor != null);
Contract.Ensures(Contract.Result<Absy>() != null);
@@ -2309,7 +2147,7 @@ namespace Microsoft.Boogie {
}
}
- public class MapSelect : IAppliable, AI.IFunctionSymbol {
+ public class MapSelect : IAppliable {
public readonly int Arity;
private readonly IToken/*!*/ tok;
@@ -2361,7 +2199,7 @@ namespace Microsoft.Boogie {
bool withRhs) {
Contract.Requires(args != null);
Contract.Requires(stream != null);
- const int opBindingStrength = 0x80;
+ const int opBindingStrength = 0x90;
bool parensNeeded = opBindingStrength < contextBindingStrength ||
(fragileContext && opBindingStrength == contextBindingStrength);
@@ -2484,40 +2322,13 @@ namespace Microsoft.Boogie {
return Type.InferValueType(mapType.TypeParameters, mapType.Arguments, mapType.Result, actualArgTypes);
}
- public AI.IFunctionSymbol/*!*/ AIFunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
-
- switch (Arity) {
- case 1:
- return AI.Heap.Select1;
- case 2:
- return AI.Heap.Select2;
- default:
- // Maps with Arity arguments are not fully supported yet
- return AI.Heap.UnsupportedHeapOp;
- }
- }
- }
-
- public AI.AIType/*!*/ AIType {
- [Rep]
- [ResultNotNewlyAllocated]
- get {
- Contract.Ensures(Contract.Result<AIType>() != null);
-
- return AI.Prop.Type; // THAT is a type? PR: no idea whether this makes sense,
- // but it is the type of select1
- }
- }
-
public T Dispatch<T>(IAppliableVisitor<T> visitor) {
//Contract.Requires(visitor != null);
return visitor.Visit(this);
}
}
- public class MapStore : IAppliable, AI.IFunctionSymbol {
+ public class MapStore : IAppliable {
public readonly int Arity;
public readonly IToken/*!*/ tok;
@@ -2631,32 +2442,6 @@ namespace Microsoft.Boogie {
return cce.NonNull(args[0]).ShallowType;
}
- public AI.IFunctionSymbol/*!*/ AIFunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
-
- switch (Arity) {
- case 1:
- return AI.Heap.Update1;
- case 2:
- return AI.Heap.Update2;
- default:
- // Maps with Arity arguments are not fully supported yet
- return AI.Heap.UnsupportedHeapOp;
- }
- }
- }
-
- public AI.AIType/*!*/ AIType {
- [Rep]
- [ResultNotNewlyAllocated]
- get {
- Contract.Ensures(Contract.Result<AIType>() != null);
-
- return AI.Heap.Type;
- }
- }
-
public T Dispatch<T>(IAppliableVisitor<T> visitor) {
//Contract.Requires(visitor != null);
return visitor.Visit(this);
@@ -2664,7 +2449,7 @@ namespace Microsoft.Boogie {
}
- public class IfThenElse : IAppliable, AI.IFunctionSymbol {
+ public class IfThenElse : IAppliable {
public IToken/*!*/ tok;
[ContractInvariantMethod]
@@ -2758,23 +2543,6 @@ namespace Microsoft.Boogie {
return cce.NonNull(args[1]).ShallowType;
}
- public AI.IFunctionSymbol/*!*/ AIFunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
- return this;
- }
- }
-
- public AI.AIType/*!*/ AIType {
- [Rep]
- [ResultNotNewlyAllocated]
- get {
- Contract.Ensures(Contract.Result<AIType>() != null);
-
- return AI.Value.FunctionType(3);
- }
- }
-
public T Dispatch<T>(IAppliableVisitor<T> visitor) {
//Contract.Requires(visitor != null);
return visitor.Visit(this);
@@ -2783,7 +2551,7 @@ namespace Microsoft.Boogie {
- public class CodeExpr : Expr, AI.IUnknown {
+ public class CodeExpr : Expr {
public VariableSeq/*!*/ LocVars;
[Rep]
public List<Block/*!*/>/*!*/ Blocks;
@@ -2802,18 +2570,6 @@ namespace Microsoft.Boogie {
Blocks = blocks;
}
- public override AI.IExpr/*!*/ IExpr {
- get {
- Contract.Ensures(Contract.Result<IExpr>() != null);
- return this;
- }
- }
- [Pure]
- public object DoVisit(AI.ExprVisitor visitor) {
- //Contract.Requires(visitor != null);
- return this;
- }
-
public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
//Contract.Requires(freeVars != null);
// Treat a BlockEexpr as if it has no free variables at all
@@ -2894,7 +2650,7 @@ namespace Microsoft.Boogie {
}
}
- public class BvExtractExpr : Expr, AI.IFunApp {
+ public class BvExtractExpr : Expr {
public /*readonly--except in StandardVisitor*/ Expr/*!*/ Bitvector;
[ContractInvariantMethod]
void ObjectInvariant() {
@@ -2934,7 +2690,7 @@ namespace Microsoft.Boogie {
public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
//Contract.Requires(stream != null);
stream.SetToken(this);
- int opBindingStrength = 0x80;
+ int opBindingStrength = 0x90;
bool parensNeeded = opBindingStrength < contextBindingStrength ||
(fragileContext && opBindingStrength == contextBindingStrength);
@@ -2987,56 +2743,6 @@ namespace Microsoft.Boogie {
}
}
- public override AI.IExpr/*!*/ IExpr {
- get {
- Contract.Ensures(Contract.Result<IExpr>() != null);
-
- return this;
- }
- }
- public AI.IFunctionSymbol/*!*/ FunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
-
- return AI.Bv.Extract;
- }
- }
- public IList/*<AI.IExpr!>*//*!*/ Arguments {
- get {
- Contract.Ensures(Contract.Result<IList>() != null);
-
- AI.IExpr[] a = new AI.IExpr[3];
- a[0] = Bitvector.IExpr;
- a[1] = new LiteralExpr(Token.NoToken, BigNum.FromInt(End));
- a[2] = new LiteralExpr(Token.NoToken, BigNum.FromInt(Start));
- return ArrayList.ReadOnly(a);
- }
- }
- public AI.IFunApp CloneWithArguments(IList/*<AI.IExpr!>*/ args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- AI.IFunApp retFun;
-
- if (args.Count == 3) {
- retFun = new BvExtractExpr(this.tok,
- BoogieFactory.IExpr2Expr(cce.NonNull((AI.IExpr)args[0])),
- cce.NonNull((LiteralExpr/*!*/)args[1]).asBigNum.ToIntSafe,
- cce.NonNull((LiteralExpr/*!*/)args[2]).asBigNum.ToIntSafe);
- } else {
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // If we are something wrong is happended
- }
- return retFun;
- }
-
- [Pure]
- public object DoVisit(AI.ExprVisitor visitor) {
- //Contract.Requires(visitor != null);
- return visitor.VisitFunApp(this);
- }
-
public override Absy StdDispatch(StandardVisitor visitor) {
//Contract.Requires(visitor != null);
Contract.Ensures(Contract.Result<Absy>() != null);
@@ -3044,7 +2750,7 @@ namespace Microsoft.Boogie {
}
}
- public class BvConcatExpr : Expr, AI.IFunApp {
+ public class BvConcatExpr : Expr {
public /*readonly--except in StandardVisitor*/ Expr/*!*/ E0, E1;
[ContractInvariantMethod]
void ObjectInvariant() {
@@ -3137,53 +2843,6 @@ namespace Microsoft.Boogie {
}
}
- public override AI.IExpr/*!*/ IExpr {
- get {
- Contract.Ensures(Contract.Result<IExpr>() != null);
-
- return this;
- }
- }
- public AI.IFunctionSymbol/*!*/ FunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
- return AI.Bv.Concat;
- }
- }
- public IList/*<AI.IExpr!>*//*!*/ Arguments {
- get {
- Contract.Ensures(Contract.Result<IList>() != null);
-
- AI.IExpr[] a = new AI.IExpr[2];
- a[0] = E0.IExpr;
- a[1] = E1.IExpr;
- return ArrayList.ReadOnly(a);
- }
- }
- public AI.IFunApp CloneWithArguments(IList/*<AI.IExpr!>*/ args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- AI.IFunApp/*!*/ retFun;
-
- if (args.Count == 2) {
- retFun = new BvConcatExpr(this.tok,
- BoogieFactory.IExpr2Expr(cce.NonNull((AI.IExpr/*!*/)args[0])),
- BoogieFactory.IExpr2Expr(cce.NonNull((AI.IExpr/*!*/)args[1])));
- } else {
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // If we are something wrong is happended
- }
- return retFun;
- }
-
- [Pure]
- public object DoVisit(AI.ExprVisitor visitor) {
- //Contract.Requires(visitor != null);
- return visitor.VisitFunApp(this);
- }
-
public override Absy StdDispatch(StandardVisitor visitor) {
//Contract.Requires(visitor != null);
Contract.Ensures(Contract.Result<Absy>() != null);
diff --git a/Source/Core/AbsyQuant.cs b/Source/Core/AbsyQuant.cs
index 3f798fd2..05fdb7e4 100644
--- a/Source/Core/AbsyQuant.cs
+++ b/Source/Core/AbsyQuant.cs
@@ -13,7 +13,6 @@ namespace Microsoft.Boogie {
using System.Diagnostics;
using System.Collections.Generic;
using Microsoft.Boogie.AbstractInterpretation;
- using AI = Microsoft.AbstractInterpretationFramework;
using System.Diagnostics.Contracts;
using Microsoft.Basetypes;
@@ -38,24 +37,11 @@ namespace Microsoft.Boogie {
public BinderExprContracts():base(null,null,null,null,null){
}
- public override Microsoft.AbstractInterpretationFramework.IFunctionSymbol FunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<AI.IFunctionSymbol>() != null);
- throw new NotImplementedException();
- }
- }
-
public override Type ShallowType {
get {
throw new NotImplementedException();
}
}
-
- public override Microsoft.AbstractInterpretationFramework.IExpr IExpr {
- get {
- throw new NotImplementedException();
- }
- }
}
[ContractClass(typeof(BinderExprContracts))]
public abstract class BinderExpr : Expr {
@@ -217,211 +203,6 @@ namespace Microsoft.Boogie {
}
return unmentionedParameters;
}
-
-
- public abstract AI.IFunctionSymbol/*!*/ FunctionSymbol {
- get;
- }
-
- internal sealed class AIQuantifier : AI.IFunApp {
- internal readonly AIFunctionRep/*!*/ arg;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(arg != null);
- }
-
- internal AIQuantifier(BinderExpr/*!*/ realQuantifier, int dummyIndex)
- : this(new AIFunctionRep(realQuantifier, dummyIndex)) {
- Contract.Requires(realQuantifier != null);
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is AIQuantifier))
- return false;
-
- AIQuantifier other = (AIQuantifier)obj;
- return object.Equals(this.arg, other.arg);
- }
- [Pure]
- public override int GetHashCode() {
- return this.arg.GetHashCode();
- }
-
- private AIQuantifier(AIFunctionRep arg) {
- Contract.Requires(arg != null);
- this.arg = arg;
- // base();
- }
-
- [Pure]
- public object DoVisit(AI.ExprVisitor visitor) {
- //Contract.Requires(visitor != null);
- return visitor.VisitFunApp(this);
- }
-
- public AI.IFunctionSymbol/*!*/ FunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<AI.IFunctionSymbol>() != null);
- return arg.RealQuantifier.FunctionSymbol;
- }
- }
-
- private IList/*?*/ argCache = null;
- public IList/*<IExpr!>*//*!*/ Arguments {
-
- get {
- Contract.Ensures(Contract.Result<IList>() != null);
-
- if (argCache == null) {
- IList a = new ArrayList(1);
- a.Add(arg);
- argCache = ArrayList.ReadOnly(a);
- }
- return argCache;
- }
- }
-
- public AI.IFunApp CloneWithArguments(IList/*<IExpr!>*/ args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<AI.IFunApp>() != null);
- Contract.Assume(args.Count == 1);
-
- AIFunctionRep rep = args[0] as AIFunctionRep;
- if (rep != null)
- return new AIQuantifier(rep);
- else
- throw new System.NotImplementedException();
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return string.Format("{0}({1})", FunctionSymbol, arg);
- }
- }
-
- internal sealed class AIFunctionRep : AI.IFunction {
- internal readonly BinderExpr/*!*/ RealQuantifier;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(RealQuantifier != null);
- }
-
- private readonly int dummyIndex;
-
- internal AIFunctionRep(BinderExpr realQuantifier, int dummyIndex) {
- Contract.Requires(realQuantifier != null);
- this.RealQuantifier = realQuantifier;
- this.dummyIndex = dummyIndex;
- Contract.Assert(realQuantifier.TypeParameters.Length == 0); // PR: don't know how to handle this yet
- // base();
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is AIFunctionRep))
- return false;
-
- AIFunctionRep other = (AIFunctionRep)obj;
- return object.Equals(this.RealQuantifier, other.RealQuantifier) && this.dummyIndex == other.dummyIndex;
- }
- [Pure]
- public override int GetHashCode() {
- return this.RealQuantifier.GetHashCode() ^ dummyIndex;
- }
-
- [Pure]
- public object DoVisit(AI.ExprVisitor visitor) {
- //Contract.Requires(visitor != null);
- return visitor.VisitFunction(this);
- }
-
- public AI.IVariable/*!*/ Param {
-
- get {
- Contract.Ensures(Contract.Result<AI.IVariable>() != null);
- return cce.NonNull(RealQuantifier.Dummies[dummyIndex]);
- }
- }
- public AI.AIType/*!*/ ParamType {
- get {
- Contract.Ensures(Contract.Result<AI.AIType>() != null);
- throw new System.NotImplementedException();
- }
- }
-
- // We lazily convert to 1 dummy per quantifier representation for AIFramework
- private AI.IExpr/*?*/ bodyCache = null;
- public AI.IExpr/*!*/ Body {
- get {
- Contract.Ensures(Contract.Result<AI.IExpr>() != null);
-
- if (bodyCache == null) {
- int dummyi = dummyIndex;
- int dummylen = RealQuantifier.Dummies.Length;
- Contract.Assume(dummylen > dummyi);
-
- // return the actual body if there are no more dummies
- if (dummyi + 1 == dummylen)
- bodyCache = RealQuantifier.Body.IExpr;
- else {
- AIQuantifier innerquant = new AIQuantifier(RealQuantifier, dummyi + 1);
- bodyCache = innerquant;
- }
- }
- return bodyCache;
- }
- }
- public AI.IFunction CloneWithBody(AI.IExpr body) {
- //Contract.Requires(body != null);
- Contract.Ensures(Contract.Result<AI.IFunction>() != null);
- BinderExpr realquant;
-
- AIQuantifier innerquant = body as AIQuantifier;
- if (innerquant == null) {
- // new quantifier body, clone the real quantifier
- realquant = (BinderExpr)RealQuantifier.Clone();
- realquant.Body = BoogieFactory.IExpr2Expr(body);
- } else {
- if (innerquant.arg.dummyIndex > 0) {
- realquant = innerquant.arg.RealQuantifier;
- } else {
- realquant = (BinderExpr)RealQuantifier.Clone();
- VariableSeq/*!*/ newdummies = new VariableSeq();
- newdummies.Add(Param);
- newdummies.AddRange(innerquant.arg.RealQuantifier.Dummies);
- realquant.Dummies = newdummies;
- realquant.Body = innerquant.arg.RealQuantifier.Body;
- }
- }
-
- return new AIFunctionRep(realquant, dummyIndex);
- }
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return string.Format("\\{0} :: {1}", Param, Body);
- }
- }
-
- private AI.IExpr aiexprCache = null;
- public override AI.IExpr/*!*/ IExpr {
- get {
- Contract.Ensures(Contract.Result<AI.IExpr>() != null);
-
- if (TypeParameters.Length > 0)
- return new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "anon", Type.Bool));
- if (aiexprCache == null) {
- aiexprCache = new AIQuantifier(this, 0);
- }
- return aiexprCache;
- }
- }
}
public class QKeyValue : Absy {
@@ -678,13 +459,6 @@ namespace Microsoft.Boogie {
Contract.Requires(dummies.Length + typeParams.Length > 0);
//:base(tok, typeParams, dummies, null, null, body); // here for aesthetic reasons
}
- public override AI.IFunctionSymbol/*!*/ FunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<AI.IFunctionSymbol>() != null);
-
- return AI.Prop.Forall;
- }
- }
public override Absy StdDispatch(StandardVisitor visitor) {
//Contract.Requires(visitor != null);
@@ -726,13 +500,6 @@ namespace Microsoft.Boogie {
Contract.Requires(dummies.Length > 0);
//:base(tok, new TypeVariableSeq(), dummies, null, null, body); // here for aesthetic reasons
}
- public override AI.IFunctionSymbol/*!*/ FunctionSymbol {
- get {
- Contract.Ensures(Contract.Result<AI.IFunctionSymbol>() != null);
-
- return AI.Prop.Exists;
- }
- }
public override Absy StdDispatch(StandardVisitor visitor) {
//Contract.Requires(visitor != null);
@@ -1006,15 +773,6 @@ namespace Microsoft.Boogie {
}
}
- public override AI.IFunctionSymbol/*!*/ FunctionSymbol {
-
- get {
- Contract.Ensures(Contract.Result<AI.IFunctionSymbol>() != null);
-
- return AI.Prop.Lambda;
- }
- }
-
public override Absy StdDispatch(StandardVisitor visitor) {
//Contract.Requires(visitor != null);
Contract.Ensures(Contract.Result<Absy>() != null);
diff --git a/Source/Core/AbsyType.cs b/Source/Core/AbsyType.cs
index a22ece7d..d78e0d34 100644
--- a/Source/Core/AbsyType.cs
+++ b/Source/Core/AbsyType.cs
@@ -13,7 +13,6 @@ namespace Microsoft.Boogie {
using System.Diagnostics;
using System.Collections.Generic;
using Microsoft.Boogie.AbstractInterpretation;
- using AI = Microsoft.AbstractInterpretationFramework;
using System.Diagnostics.Contracts;
//=====================================================================
@@ -240,6 +239,11 @@ namespace Microsoft.Boogie {
return false;
}
}
+ public virtual bool IsReal {
+ get {
+ return false;
+ }
+ }
public virtual bool IsBool {
get {
return false;
@@ -331,6 +335,7 @@ namespace Microsoft.Boogie {
}
public static readonly Type/*!*/ Int = new BasicType(SimpleType.Int);
+ public static readonly Type/*!*/ Real = new BasicType(SimpleType.Real);
public static readonly Type/*!*/ Bool = new BasicType(SimpleType.Bool);
private static BvType[] bvtypeCache;
@@ -866,6 +871,8 @@ namespace Microsoft.Boogie {
switch (T) {
case SimpleType.Int:
return "int";
+ case SimpleType.Real:
+ return "real";
case SimpleType.Bool:
return "bool";
}
@@ -983,6 +990,11 @@ namespace Microsoft.Boogie {
return this.T == SimpleType.Int;
}
}
+ public override bool IsReal {
+ get {
+ return this.T == SimpleType.Real;
+ }
+ }
public override bool IsBool {
get {
return this.T == SimpleType.Bool;
@@ -1884,6 +1896,12 @@ Contract.Requires(that != null);
return p != null && p.IsInt;
}
}
+ public override bool IsReal {
+ get {
+ Type p = ProxyFor;
+ return p != null && p.IsReal;
+ }
+ }
public override bool IsBool {
get {
Type p = ProxyFor;
@@ -2727,6 +2745,11 @@ Contract.Requires(that != null);
return ExpandedType.IsInt;
}
}
+ public override bool IsReal {
+ get {
+ return ExpandedType.IsReal;
+ }
+ }
public override bool IsBool {
get {
return ExpandedType.IsBool;
@@ -3500,6 +3523,7 @@ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
public enum SimpleType {
Int,
+ Real,
Bool
};
diff --git a/Source/Core/BoogiePL.atg b/Source/Core/BoogiePL.atg
index 9c721703..96ba9824 100644
--- a/Source/Core/BoogiePL.atg
+++ b/Source/Core/BoogiePL.atg
@@ -12,7 +12,6 @@ using System.Text;
using Microsoft.Boogie;
using Microsoft.Basetypes;
using Bpl = Microsoft.Boogie;
-using AI = Microsoft.AbstractInterpretationFramework;
COMPILER BoogiePL
@@ -115,7 +114,6 @@ private class BvBounds : Expr {
{Contract.Assert(false);throw new cce.UnreachableException();}
}
public override void ComputeFreeVariables(GSet<object>/*!*/ freeVars) {Contract.Requires(freeVars != null); {Contract.Assert(false);throw new cce.UnreachableException();} }
- public override AI.IExpr/*!*/ IExpr { get { Contract.Ensures(Contract.Result<AI.IExpr>()!=null); {Contract.Assert(false);throw new cce.UnreachableException();} } }
}
/*--------------------------------------------------------------------------*/
@@ -147,7 +145,8 @@ TOKENS
string = quote { regularStringChar | "\\\"" } quote.
- float = digit {digit} '.' {digit}.
+ decimal = digit {digit} 'e' [ '-' ] digit {digit} .
+ float = digit {digit} '.' digit {digit} [ 'e' [ '-' ] digit {digit} ] .
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
@@ -315,6 +314,7 @@ TypeArgs<TypeSeq/*!*/ ts>
TypeAtom<out Bpl.Type/*!*/ ty>
= (.Contract.Ensures(Contract.ValueAtReturn(out ty) != null); ty = dummyType; .)
( "int" (. ty = new BasicType(t, SimpleType.Int); .)
+ | "real" (. ty = new BasicType(t, SimpleType.Real); .)
| "bool" (. ty = new BasicType(t, SimpleType.Bool); .)
/* note: bitvectors are handled in UnresolvedTypeIdentifier */
|
@@ -1164,27 +1164,39 @@ AddOp<out IToken/*!*/ x, out BinaryOperator.Opcode op>
/*------------------------------------------------------------------------*/
Factor<out Expr/*!*/ e0>
= (.Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op; .)
- UnaryExpression<out e0>
+ Power<out e0>
{ MulOp<out x, out op>
- UnaryExpression<out e1> (. e0 = Expr.Binary(x, op, e0, e1); .)
+ Power<out e1> (. e0 = Expr.Binary(x, op, e0, e1); .)
}
.
MulOp<out IToken/*!*/ x, out BinaryOperator.Opcode op>
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
( "*" (. x = t; op=BinaryOperator.Opcode.Mul; .)
- | "/" (. x = t; op=BinaryOperator.Opcode.Div; .)
- | "%" (. x = t; op=BinaryOperator.Opcode.Mod; .)
+ | "div" (. x = t; op=BinaryOperator.Opcode.Div; .)
+ | "mod" (. x = t; op=BinaryOperator.Opcode.Mod; .)
+ | "/" (. x = t; op=BinaryOperator.Opcode.RealDiv; .)
)
.
/*------------------------------------------------------------------------*/
+Power<out Expr/*!*/ e0>
+= (.Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
+ UnaryExpression<out e0>
+ [
+ "**" (. x = t; .)
+ /* recurse because exponentation is right-associative */
+ Power<out e1> (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Pow, e0, e1); .)
+ ]
+ .
+
+/*------------------------------------------------------------------------*/
UnaryExpression<out Expr/*!*/ e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
e = dummyExpr;
.)
( "-" (. x = t; .)
- UnaryExpression<out e> (. e = Expr.Binary(x, BinaryOperator.Opcode.Sub, new LiteralExpr(x, BigNum.ZERO), e); .)
+ UnaryExpression<out e> (. e = Expr.Unary(x, UnaryOperator.Opcode.Neg, e); .)
| NegOp (. x = t; .)
UnaryExpression<out e> (. e = Expr.Unary(x, UnaryOperator.Opcode.Not, e); .)
| CoercionExpression<out e>
@@ -1273,7 +1285,7 @@ ArrayExpression<out Expr/*!*/ e>
/*------------------------------------------------------------------------*/
AtomExpression<out Expr/*!*/ e>
-= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn;
+= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn; BigDec bd;
ExprSeq/*!*/ es; VariableSeq/*!*/ ds; Trigger trig;
TypeVariableSeq/*!*/ typeParams;
IdentifierExpr/*!*/ id;
@@ -1285,6 +1297,7 @@ AtomExpression<out Expr/*!*/ e>
( "false" (. e = new LiteralExpr(t, false); .)
| "true" (. e = new LiteralExpr(t, true); .)
| Nat<out bn> (. e = new LiteralExpr(t, bn); .)
+ | Dec<out bd> (. e = new LiteralExpr(t, bd); .)
| BvLit<out bn, out n> (. e = new LiteralExpr(t, bn, n); .)
| Ident<out x> (. id = new IdentifierExpr(x, x.val); e = id; .)
@@ -1300,6 +1313,16 @@ AtomExpression<out Expr/*!*/ e>
Expression<out e>
")" (. e = new OldExpr(x, e); .)
+ | "int" (. x = t; .)
+ "("
+ Expression<out e>
+ ")" (. e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToInt), new ExprSeq(e)); .)
+
+ | "real" (. x = t; .)
+ "("
+ Expression<out e>
+ ")" (. e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToReal), new ExprSeq(e)); .)
+
| "(" ( Expression<out e> (. if (e is BvBounds)
this.SemErr("parentheses around bitvector bounds " +
"are not allowed"); .)
@@ -1484,6 +1507,23 @@ Nat<out BigNum n>
.
/*------------------------------------------------------------------------*/
+Dec<out BigDec n>
+= (. string s = ""; .)
+ (
+ decimal (. s = t.val; .)
+ |
+ float (. s = t.val; .)
+ )
+ (. try {
+ n = BigDec.FromString(s);
+ } catch (FormatException) {
+ this.SemErr("incorrectly formatted number");
+ n = BigDec.ZERO;
+ }
+ .)
+ .
+
+/*------------------------------------------------------------------------*/
BvLit<out BigNum n, out int m>
=
bvlit
diff --git a/Source/Core/CommandLineOptions.cs b/Source/Core/CommandLineOptions.cs
index 73fa8946..4192259d 100644
--- a/Source/Core/CommandLineOptions.cs
+++ b/Source/Core/CommandLineOptions.cs
@@ -575,8 +575,6 @@ namespace Microsoft.Boogie {
public string CoverageReporterPath = null;
public Process coverageReporter = null; // used internally for debugging
- public bool DoPredication = false;
-
public enum TypeEncoding {
None,
Predicates,
@@ -609,26 +607,9 @@ namespace Microsoft.Boogie {
}
public class AiFlags {
- public bool Intervals = false;
- public bool Constant = false;
- public bool DynamicType = false;
- public bool Nullness = false;
- public bool Polyhedra = false;
public bool J_Trivial = false;
public bool J_Intervals = false;
public bool DebugStatistics = false;
-
- public bool AnySet {
- get {
- return Intervals
- || Constant
- || DynamicType
- || Nullness
- || Polyhedra
- || J_Trivial
- || J_Intervals;
- }
- }
}
public AiFlags/*!*/ Ai = new AiFlags();
@@ -639,26 +620,6 @@ namespace Microsoft.Boogie {
if (ps.ConfirmArgumentCount(1)) {
foreach (char c in cce.NonNull(args[ps.i])) {
switch (c) {
- case 'i':
- Ai.Intervals = true;
- UseAbstractInterpretation = true;
- break;
- case 'c':
- Ai.Constant = true;
- UseAbstractInterpretation = true;
- break;
- case 'd':
- Ai.DynamicType = true;
- UseAbstractInterpretation = true;
- break;
- case 'n':
- Ai.Nullness = true;
- UseAbstractInterpretation = true;
- break;
- case 'p':
- Ai.Polyhedra = true;
- UseAbstractInterpretation = true;
- break;
case 't':
Ai.J_Trivial = true;
UseAbstractInterpretation = true;
@@ -697,12 +658,6 @@ namespace Microsoft.Boogie {
}
return true;
- case "logInfer":
- if (ps.ConfirmArgumentCount(0)) {
- Microsoft.AbstractInterpretationFramework.Lattice.LogSwitch = true;
- }
- return true;
-
case "break":
case "launch":
if (ps.ConfirmArgumentCount(0)) {
@@ -1133,6 +1088,18 @@ namespace Microsoft.Boogie {
ps.GetNumericArgument(ref VcsCores);
return true;
+ case "vcsLoad":
+ double load = 0.0;
+ if (ps.GetNumericArgument(ref load)) {
+ if (3.0 <= load) {
+ ps.Error("surprisingly high load specified; got {0}, expected nothing above 3.0", load.ToString());
+ load = 3.0;
+ }
+ int p = (int)Math.Round(System.Environment.ProcessorCount * load);
+ VcsCores = p < 1 ? 1 : p;
+ }
+ return true;
+
case "simplifyMatchDepth":
ps.GetNumericArgument(ref SimplifyProverMatchDepth);
return true;
@@ -1234,8 +1201,7 @@ namespace Microsoft.Boogie {
ps.CheckBooleanFlag("useUnsatCoreForContractInfer", ref UseUnsatCoreForContractInfer) ||
ps.CheckBooleanFlag("printAssignment", ref PrintAssignment) ||
ps.CheckBooleanFlag("nonUniformUnfolding", ref NonUniformUnfolding) ||
- ps.CheckBooleanFlag("deterministicExtractLoops", ref DeterministicExtractLoops) ||
- ps.CheckBooleanFlag("predicate", ref DoPredication)
+ ps.CheckBooleanFlag("deterministicExtractLoops", ref DeterministicExtractLoops)
) {
// one of the boolean flags matched
return true;
@@ -1502,7 +1468,6 @@ namespace Microsoft.Boogie {
perform interprocedural inference (deprecated, not supported)
/contractInfer
perform procedure contract inference
- /logInfer print debug output during inference
/instrumentInfer
h - instrument inferred invariants only at beginning of
loop headers (default)
@@ -1642,6 +1607,9 @@ namespace Microsoft.Boogie {
Warning: Affects error reporting.
/vcsCores:<n>
Try to verify <n> VCs at once. Defaults to 1.
+ /vcsLoad:<f> Sets vcsCores to the machine's ProcessorCount * f,
+ rounded to the nearest integer (where 0.0 <= f <= 3.0),
+ but never to less than 1.
---- Prover options --------------------------------------------------------
diff --git a/Source/Core/Core.csproj b/Source/Core/Core.csproj
index 9a24b6b2..49639822 100644
--- a/Source/Core/Core.csproj
+++ b/Source/Core/Core.csproj
@@ -155,7 +155,6 @@
<Compile Include="CommandLineOptions.cs" />
<Compile Include="DeadVarElim.cs" />
<Compile Include="Duplicator.cs" />
- <Compile Include="GraphAlgorithms.cs" />
<Compile Include="Inline.cs" />
<Compile Include="LambdaHelper.cs" />
<Compile Include="LoopUnroll.cs" />
@@ -172,10 +171,6 @@
<Compile Include="Xml.cs" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
<ProjectReference Include="..\Basetypes\Basetypes.csproj">
<Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
<Name>Basetypes</Name>
diff --git a/Source/Core/DeadVarElim.cs b/Source/Core/DeadVarElim.cs
index 1376245a..5bf306b6 100644
--- a/Source/Core/DeadVarElim.cs
+++ b/Source/Core/DeadVarElim.cs
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
-using Graphing;
+using Microsoft.Boogie.GraphUtil;
using PureCollections;
using System.Diagnostics.Contracts;
@@ -355,7 +355,7 @@ namespace Microsoft.Boogie {
public static void ComputeLiveVariables(Implementation impl) {
Contract.Requires(impl != null);
Microsoft.Boogie.Helpers.ExtraTraceInformation("Starting live variable analysis");
- Graphing.Graph<Block> dag = new Graph<Block>();
+ Graph<Block> dag = new Graph<Block>();
dag.AddSource(cce.NonNull(impl.Blocks[0])); // there is always at least one node in the graph
foreach (Block b in impl.Blocks) {
GotoCmd gtc = b.TransferCmd as GotoCmd;
diff --git a/Source/Core/GraphAlgorithms.cs b/Source/Core/GraphAlgorithms.cs
deleted file mode 100644
index a19cf96c..00000000
--- a/Source/Core/GraphAlgorithms.cs
+++ /dev/null
@@ -1,244 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.Boogie {
- public delegate System.Collections.IEnumerable/*<Node!>*//*!*/ Adjacency<T>(T/*!*/ node);
-
-
- // An SCC is a set of nodes
- public sealed class SCC<Node> : ICollection<Node> {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(nodesMap != null);
- }
-
- private IDictionary<Node, object>/*!*/ nodesMap = new Dictionary<Node, object>();
- private ICollection<Node>/*!*/ nodes {
- get {
- return cce.NonNull(nodesMap.Keys);
- }
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- System.Collections.IEnumerator/*!*/ System.Collections.IEnumerable.GetEnumerator() {
- Contract.Ensures(Contract.Result<System.Collections.IEnumerator>() != null);
-
- return ((System.Collections.IEnumerable)nodes).GetEnumerator();
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- IEnumerator<Node>/*!*/ IEnumerable<Node>.GetEnumerator() {
- Contract.Ensures(Contract.Result<IEnumerator<Node>>() != null);
-
- return ((IEnumerable<Node>)nodes).GetEnumerator();
- }
-
- public int Count {
- get {
- return nodes.Count;
- }
- }
- public bool IsReadOnly {
- get {
- return nodesMap.IsReadOnly;
- }
- }
- public void Add(Node item) {
- nodesMap.Add(item, null);
- }
- public void Clear() {
- nodesMap.Clear();
- }
- [Pure]
- public bool Contains(Node item) {
- return nodesMap.ContainsKey(item);
- }
- public void CopyTo(Node[] array, int arrayIndex) {
- //Contract.Requires(array != null);
- nodes.CopyTo(array, arrayIndex);
- }
- public bool Remove(Node item) {
- return nodesMap.Remove(item);
- }
- }
-
- public sealed class StronglyConnectedComponents<Node> : IEnumerable<SCC<Node>/*!*/> where Node : class {
- private readonly IDictionary<Node/*!*/, object>/*!*/ graph;
- [ContractInvariantMethod]
- void graphInvariantMethod() {
- Contract.Invariant(Contract.ForAll(graph, entry => entry.Key != null));
- Contract.Invariant(preds != null);
- Contract.Invariant(succs != null);
- }
- private readonly Adjacency<Node>/*!*/ preds;
- private readonly Adjacency<Node>/*!*/ succs;
-
- private bool computed = false;
- public bool Computed {
- get {
- return computed;
- }
- }
-
- [NotDelayed]
- public StronglyConnectedComponents(System.Collections.IEnumerable/*<Node!>*/ graph, Adjacency<Node> preds, Adjacency<Node> succs)
- : base() {//BASEMOVE DANGER
- Contract.Requires(succs != null);
- Contract.Requires(preds != null);
- Contract.Requires(graph != null);
- Contract.Ensures(!Computed);
- IDictionary<Node/*!*/, object>/*!*/ dict = new Dictionary<Node/*!*/, object>();
- foreach (Node/*!*/ n in graph) {
- Contract.Assert(n != null);
- dict.Add(n, null);
- }
-
- this.graph = dict;
- this.preds = preds;
- this.succs = succs;
- //:base();
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- System.Collections.IEnumerator/*!*/ System.Collections.IEnumerable.GetEnumerator() {
- Contract.Ensures(Contract.Result<System.Collections.IEnumerator>() != null);
-
- return ((System.Collections.IEnumerable)sccs).GetEnumerator();
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- IEnumerator<SCC<Node>/*!*/>/*!*/ IEnumerable<SCC<Node>/*!*/>.GetEnumerator() {
- Contract.Ensures(Contract.Result<IEnumerator<SCC<Node>>>() != null);
-
- Contract.Assume(Computed);
- Contract.Assert(cce.NonNullElements((IEnumerable<SCC<Node>/*!*/>)sccs));//REVIEW
- return ((IEnumerable<SCC<Node>/*!*/>)sccs).GetEnumerator();
- }
-
- private readonly IList<SCC<Node>/*!*/>/*!*/ sccs = new List<SCC<Node>/*!*/>();
- [ContractInvariantMethod]
- void sccsInvariant() {
- Contract.Invariant(cce.NonNullElements(sccs));
- }
-
-
- public void Compute() {
- Contract.Requires(!Computed);
- Contract.Ensures(Computed);
- // Compute post times on graph with edges reversed
- this.dfsNext = this.preds;
- foreach (Node/*!*/ n in cce.NonNull(graph.Keys)) {
- Contract.Assert(n != null);
- if (!seen.ContainsKey(n)) {
- OrderNodes(n);
- }
- }
-
- // Clear seen
- seen.Clear();
-
- // Compute SCCs
- this.dfsNext = this.succs;
- while (postOrder.Count > 0) {
- Node/*!*/ n = postOrder.Pop();
- Contract.Assert(n != null);
-
- if (!seen.ContainsKey(n)) {
- SCC<Node>/*!*/ curr = new SCC<Node>();
- FindSCCs(n, curr);
- sccs.Add(curr);
- }
- }
-
- // Clear seen
- seen.Clear();
-
- this.computed = true;
- }
-
- private Adjacency<Node>/*?*/ dfsNext = null;
-
- private readonly IDictionary<Node/*!*/, object>/*!*/ seen = new Dictionary<Node/*!*/, object>();
- private readonly Stack<Node/*!*/>/*!*/ postOrder = new Stack<Node/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(seen != null);
- Contract.Invariant(cce.NonNullElements(postOrder));
- }
-
-
- // DFS to order nodes by post times
- private void OrderNodes(Node node) {
- Contract.Requires(node != null);
- seen.Add(node, null);
-
- Contract.Assert(dfsNext != null);
- System.Collections.IEnumerable/*!*/ nexts = dfsNext(node);
- Contract.Assert(nexts != null);
- foreach (Node/*!*/ n in nexts) {
- Contract.Assert(n != null);
- if (graph.ContainsKey(n) && !seen.ContainsKey(n)) {
- OrderNodes(n);
- }
- }
-
- postOrder.Push(node);
- }
-
- // DFS to compute SCCs
- private void FindSCCs(Node node, SCC<Node> currSCC) {
- Contract.Requires(currSCC != null);
- Contract.Requires(node != null);
- //modifies currSCC.*;
- seen.Add(node, null);
- currSCC.Add(node);
-
- Contract.Assert(dfsNext != null);
- System.Collections.IEnumerable/*!*/ nexts = dfsNext(node);
- Contract.Assert(nexts != null);
- foreach (Node/*!*/ n in nexts) {
- Contract.Assert(n != null);
- if (graph.ContainsKey(n) && !seen.ContainsKey(n)) {
- FindSCCs(n, currSCC);
- }
- }
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- string outStr = "";
- int i = 0;
-
- foreach (ICollection<Node> component in this) {
- string/*!*/ tmp = System.String.Format("\nComponent #{0} = ", i++);
- Contract.Assert(tmp != null);
- outStr += tmp;
-
- bool firstInRow = true;
-
- foreach (Node b in component) {
- string/*!*/ tmpComponent = System.String.Format("{0}{1}", firstInRow ? "" : ", ", b);
- Contract.Assert(tmpComponent != null);
- outStr += tmpComponent;
- firstInRow = false;
- }
- }
- return outStr;
- }
-
- }
-}
diff --git a/Source/Core/LoopUnroll.cs b/Source/Core/LoopUnroll.cs
index 3b61ad3e..580cbdc5 100644
--- a/Source/Core/LoopUnroll.cs
+++ b/Source/Core/LoopUnroll.cs
@@ -6,6 +6,7 @@
using System.Diagnostics.Contracts;
using System.Collections.Generic;
using Bpl = Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
namespace Microsoft.Boogie {
public class LoopUnroll {
diff --git a/Source/Core/Makefile b/Source/Core/Makefile
index 192a16db..4d3f433a 100644
--- a/Source/Core/Makefile
+++ b/Source/Core/Makefile
@@ -10,10 +10,11 @@ FRAME_DIR = ..\..\..\boogiepartners\CocoR\Modified
# "all" depends on 2 files, really (Parser.cs and Scanner.cs), but they
# are both generated in one go and I don't know a better way to tell
# nmake that. --KRML
-all: Parser.ssc
+all: Parser.cs
-Parser.ssc: $(FRAME_DIR)\Scanner.frame $(FRAME_DIR)\Parser.frame BoogiePL.atg
+Parser.cs: $(FRAME_DIR)\Scanner.frame $(FRAME_DIR)\Parser.frame BoogiePL.atg
$(COCO) BoogiePL.atg -namespace Microsoft.Boogie -frames $(FRAME_DIR)
clean:
- rm -f Scanner.cs Parser.cs
+ if exist Scanner.cs del Scanner.cs
+ if exist Parser.cs del Parser.cs
diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs
index 69f505bc..0a10b0a1 100644
--- a/Source/Core/Parser.cs
+++ b/Source/Core/Parser.cs
@@ -6,7 +6,6 @@ using System.Text;
using Microsoft.Boogie;
using Microsoft.Basetypes;
using Bpl = Microsoft.Boogie;
-using AI = Microsoft.AbstractInterpretationFramework;
@@ -24,8 +23,9 @@ public class Parser {
public const int _bvlit = 2;
public const int _digits = 3;
public const int _string = 4;
- public const int _float = 5;
- public const int maxT = 88;
+ public const int _decimal = 5;
+ public const int _float = 6;
+ public const int maxT = 92;
const bool T = true;
const bool x = false;
@@ -134,7 +134,6 @@ private class BvBounds : Expr {
{Contract.Assert(false);throw new cce.UnreachableException();}
}
public override void ComputeFreeVariables(GSet<object>/*!*/ freeVars) {Contract.Requires(freeVars != null); {Contract.Assert(false);throw new cce.UnreachableException();} }
- public override AI.IExpr/*!*/ IExpr { get { Contract.Ensures(Contract.Result<AI.IExpr>()!=null); {Contract.Assert(false);throw new cce.UnreachableException();} } }
}
/*--------------------------------------------------------------------------*/
@@ -219,7 +218,7 @@ private class BvBounds : Expr {
while (StartOf(1)) {
switch (la.kind) {
- case 19: {
+ case 21: {
Consts(out vs);
foreach(Bpl.Variable/*!*/ v in vs){
Contract.Assert(v != null);
@@ -228,7 +227,7 @@ private class BvBounds : Expr {
break;
}
- case 23: {
+ case 25: {
Function(out ds);
foreach(Bpl.Declaration/*!*/ d in ds){
Contract.Assert(d != null);
@@ -237,12 +236,12 @@ private class BvBounds : Expr {
break;
}
- case 27: {
+ case 29: {
Axiom(out ax);
Pgm.TopLevelDeclarations.Add(ax);
break;
}
- case 28: {
+ case 30: {
UserDefinedTypes(out ts);
foreach(Declaration/*!*/ td in ts){
Contract.Assert(td != null);
@@ -251,7 +250,7 @@ private class BvBounds : Expr {
break;
}
- case 6: {
+ case 7: {
GlobalVars(out vs);
foreach(Bpl.Variable/*!*/ v in vs){
Contract.Assert(v != null);
@@ -260,7 +259,7 @@ private class BvBounds : Expr {
break;
}
- case 30: {
+ case 32: {
Procedure(out pr, out im);
Pgm.TopLevelDeclarations.Add(pr);
if (im != null) {
@@ -269,7 +268,7 @@ private class BvBounds : Expr {
break;
}
- case 31: {
+ case 33: {
Implementation(out nnim);
Pgm.TopLevelDeclarations.Add(nnim);
break;
@@ -285,17 +284,17 @@ private class BvBounds : Expr {
bool u = false; QKeyValue kv = null;
bool ChildrenComplete = false;
List<ConstantParent/*!*/> Parents = null;
- Expect(19);
+ Expect(21);
y = t;
- while (la.kind == 25) {
+ while (la.kind == 27) {
Attribute(ref kv);
}
- if (la.kind == 20) {
+ if (la.kind == 22) {
Get();
u = true;
}
IdsType(out xs);
- if (la.kind == 21) {
+ if (la.kind == 23) {
OrderSpec(out ChildrenComplete, out Parents);
}
bool makeClone = false;
@@ -319,7 +318,7 @@ private class BvBounds : Expr {
ds.Add(new Constant(y, x, u, ParentsClone, ChildrenComplete, kv));
}
- Expect(7);
+ Expect(8);
}
void Function(out DeclarationSeq/*!*/ ds) {
@@ -335,44 +334,44 @@ private class BvBounds : Expr {
Expr definition = null;
Expr/*!*/ tmp;
- Expect(23);
- while (la.kind == 25) {
+ Expect(25);
+ while (la.kind == 27) {
Attribute(ref kv);
}
Ident(out z);
- if (la.kind == 17) {
+ if (la.kind == 19) {
TypeParams(out typeParamTok, out typeParams);
}
- Expect(8);
+ Expect(9);
if (StartOf(2)) {
VarOrType(out tyd);
arguments.Add(new Formal(tyd.tok, tyd, true));
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
VarOrType(out tyd);
arguments.Add(new Formal(tyd.tok, tyd, true));
}
}
- Expect(9);
- if (la.kind == 24) {
+ Expect(10);
+ if (la.kind == 26) {
Get();
- Expect(8);
- VarOrType(out tyd);
Expect(9);
+ VarOrType(out tyd);
+ Expect(10);
retTyd = tyd;
- } else if (la.kind == 10) {
+ } else if (la.kind == 11) {
Get();
Type(out retTy);
retTyd = new TypedIdent(retTy.tok, "", retTy);
- } else SynErr(89);
- if (la.kind == 25) {
+ } else SynErr(93);
+ if (la.kind == 27) {
Get();
Expression(out tmp);
definition = tmp;
- Expect(26);
- } else if (la.kind == 7) {
+ Expect(28);
+ } else if (la.kind == 8) {
Get();
- } else SynErr(90);
+ } else SynErr(94);
if (retTyd == null) {
// construct a dummy type for the case of syntax error
tyd = new TypedIdent(t, "", new BasicType(t, SimpleType.Int));
@@ -453,40 +452,40 @@ private class BvBounds : Expr {
void Axiom(out Axiom/*!*/ m) {
Contract.Ensures(Contract.ValueAtReturn(out m) != null); Expr/*!*/ e; QKeyValue kv = null;
- Expect(27);
- while (la.kind == 25) {
+ Expect(29);
+ while (la.kind == 27) {
Attribute(ref kv);
}
IToken/*!*/ x = t;
Proposition(out e);
- Expect(7);
+ Expect(8);
m = new Axiom(x,e, null, kv);
}
void UserDefinedTypes(out List<Declaration/*!*/>/*!*/ ts) {
Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out ts))); Declaration/*!*/ decl; QKeyValue kv = null; ts = new List<Declaration/*!*/> ();
- Expect(28);
- while (la.kind == 25) {
+ Expect(30);
+ while (la.kind == 27) {
Attribute(ref kv);
}
UserDefinedType(out decl, kv);
ts.Add(decl);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
UserDefinedType(out decl, kv);
ts.Add(decl);
}
- Expect(7);
+ Expect(8);
}
void GlobalVars(out VariableSeq/*!*/ ds) {
Contract.Ensures(Contract.ValueAtReturn(out ds) != null); TypedIdentSeq/*!*/ tyds = new TypedIdentSeq(); ds = new VariableSeq(); QKeyValue kv = null;
- Expect(6);
- while (la.kind == 25) {
+ Expect(7);
+ while (la.kind == 27) {
Attribute(ref kv);
}
IdsTypeWheres(true, tyds);
- Expect(7);
+ Expect(8);
foreach(TypedIdent/*!*/ tyd in tyds){
Contract.Assert(tyd != null);
ds.Add(new GlobalVariable(tyd.tok, tyd, kv));
@@ -507,9 +506,9 @@ private class BvBounds : Expr {
QKeyValue kv = null;
impl = null;
- Expect(30);
+ Expect(32);
ProcSignature(true, out x, out typeParams, out ins, out outs, out kv);
- if (la.kind == 7) {
+ if (la.kind == 8) {
Get();
while (StartOf(3)) {
Spec(pre, mods, post);
@@ -522,7 +521,7 @@ private class BvBounds : Expr {
impl = new Implementation(x, x.val, typeParams,
Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, kv == null ? null : (QKeyValue)kv.Clone(), this.errors);
- } else SynErr(91);
+ } else SynErr(95);
proc = new Procedure(x, x.val, typeParams, ins, outs, pre, mods, post, kv);
}
@@ -534,7 +533,7 @@ private class BvBounds : Expr {
StmtList/*!*/ stmtList;
QKeyValue kv;
- Expect(31);
+ Expect(33);
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);
@@ -549,7 +548,7 @@ private class BvBounds : Expr {
void IdsTypeWheres(bool allowWhereClauses, TypedIdentSeq/*!*/ tyds) {
Contract.Requires(tyds != null);
IdsTypeWhere(allowWhereClauses, tyds);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
IdsTypeWhere(allowWhereClauses, tyds);
}
@@ -557,12 +556,12 @@ private class BvBounds : Expr {
void LocalVars(VariableSeq/*!*/ ds) {
Contract.Ensures(Contract.ValueAtReturn(out ds) != null); TypedIdentSeq/*!*/ tyds = new TypedIdentSeq(); QKeyValue kv = null;
- Expect(6);
- while (la.kind == 25) {
+ Expect(7);
+ while (la.kind == 27) {
Attribute(ref kv);
}
IdsTypeWheres(true, tyds);
- Expect(7);
+ Expect(8);
foreach(TypedIdent/*!*/ tyd in tyds){
Contract.Assert(tyd != null);
ds.Add(new LocalVariable(tyd.tok, tyd, kv));
@@ -572,11 +571,11 @@ private class BvBounds : Expr {
void ProcFormals(bool incoming, bool allowWhereClauses, out VariableSeq/*!*/ ds) {
Contract.Ensures(Contract.ValueAtReturn(out ds) != null); TypedIdentSeq/*!*/ tyds = new TypedIdentSeq(); ds = new VariableSeq();
- Expect(8);
+ Expect(9);
if (la.kind == 1) {
IdsTypeWheres(allowWhereClauses, tyds);
}
- Expect(9);
+ Expect(10);
foreach(TypedIdent/*!*/ tyd in tyds){
Contract.Assert(tyd != null);
ds.Add(new Formal(tyd.tok, tyd, incoming));
@@ -597,7 +596,7 @@ private class BvBounds : Expr {
void IdsType(out TypedIdentSeq/*!*/ tyds) {
Contract.Ensures(Contract.ValueAtReturn(out tyds) != null); TokenSeq/*!*/ ids; Bpl.Type/*!*/ ty;
Idents(out ids);
- Expect(10);
+ Expect(11);
Type(out ty);
tyds = new TypedIdentSeq();
foreach(Token/*!*/ id in ids){
@@ -611,7 +610,7 @@ private class BvBounds : Expr {
Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new TokenSeq();
Ident(out id);
xs.Add(id);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
Ident(out id);
xs.Add(id);
@@ -620,7 +619,7 @@ private class BvBounds : Expr {
void Type(out Bpl.Type/*!*/ ty) {
Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken/*!*/ tok; ty = dummyType;
- if (la.kind == 8 || la.kind == 13 || la.kind == 14) {
+ if (StartOf(5)) {
TypeAtom(out ty);
} else if (la.kind == 1) {
Ident(out tok);
@@ -629,17 +628,17 @@ private class BvBounds : Expr {
TypeArgs(args);
}
ty = new UnresolvedTypeIdentifier (tok, tok.val, args);
- } else if (la.kind == 15 || la.kind == 17) {
+ } else if (la.kind == 17 || la.kind == 19) {
MapType(out ty);
- } else SynErr(92);
+ } else SynErr(96);
}
void IdsTypeWhere(bool allowWhereClauses, TypedIdentSeq/*!*/ tyds) {
Contract.Requires(tyds != null); TokenSeq/*!*/ ids; Bpl.Type/*!*/ ty; Expr wh = null; Expr/*!*/ nne;
Idents(out ids);
- Expect(10);
+ Expect(11);
Type(out ty);
- if (la.kind == 12) {
+ if (la.kind == 13) {
Get();
Expression(out nne);
if (allowWhereClauses) {
@@ -659,7 +658,7 @@ private class BvBounds : Expr {
void Expression(out Expr/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
ImpliesExpression(false, out e0);
- while (la.kind == 50 || la.kind == 51) {
+ while (la.kind == 52 || la.kind == 53) {
EquivOp();
x = t;
ImpliesExpression(false, out e1);
@@ -669,17 +668,20 @@ private class BvBounds : Expr {
void TypeAtom(out Bpl.Type/*!*/ ty) {
Contract.Ensures(Contract.ValueAtReturn(out ty) != null); ty = dummyType;
- if (la.kind == 13) {
+ if (la.kind == 14) {
Get();
ty = new BasicType(t, SimpleType.Int);
- } else if (la.kind == 14) {
+ } else if (la.kind == 15) {
+ Get();
+ ty = new BasicType(t, SimpleType.Real);
+ } else if (la.kind == 16) {
Get();
ty = new BasicType(t, SimpleType.Bool);
- } else if (la.kind == 8) {
+ } else if (la.kind == 9) {
Get();
Type(out ty);
- Expect(9);
- } else SynErr(93);
+ Expect(10);
+ } else SynErr(97);
}
void Ident(out IToken/*!*/ x) {
@@ -693,7 +695,7 @@ private class BvBounds : Expr {
void TypeArgs(TypeSeq/*!*/ ts) {
Contract.Requires(ts != null); IToken/*!*/ tok; Type/*!*/ ty;
- if (la.kind == 8 || la.kind == 13 || la.kind == 14) {
+ if (StartOf(5)) {
TypeAtom(out ty);
ts.Add(ty);
if (StartOf(2)) {
@@ -706,10 +708,10 @@ private class BvBounds : Expr {
if (StartOf(2)) {
TypeArgs(ts);
}
- } else if (la.kind == 15 || la.kind == 17) {
+ } else if (la.kind == 17 || la.kind == 19) {
MapType(out ty);
ts.Add(ty);
- } else SynErr(94);
+ } else SynErr(98);
}
void MapType(out Bpl.Type/*!*/ ty) {
@@ -719,16 +721,16 @@ private class BvBounds : Expr {
Type/*!*/ result;
TypeVariableSeq/*!*/ typeParameters = new TypeVariableSeq();
- if (la.kind == 17) {
+ if (la.kind == 19) {
TypeParams(out nnTok, out typeParameters);
tok = nnTok;
}
- Expect(15);
+ Expect(17);
if (tok == null) tok = t;
if (StartOf(2)) {
Types(arguments);
}
- Expect(16);
+ Expect(18);
Type(out result);
ty = new MapType(tok, typeParameters, arguments, result);
@@ -736,10 +738,10 @@ private class BvBounds : Expr {
void TypeParams(out IToken/*!*/ tok, out Bpl.TypeVariableSeq/*!*/ typeParams) {
Contract.Ensures(Contract.ValueAtReturn(out tok) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); TokenSeq/*!*/ typeParamToks;
- Expect(17);
+ Expect(19);
tok = t;
Idents(out typeParamToks);
- Expect(18);
+ Expect(20);
typeParams = new TypeVariableSeq ();
foreach(Token/*!*/ id in typeParamToks){
Contract.Assert(id != null);
@@ -751,7 +753,7 @@ private class BvBounds : Expr {
Contract.Requires(ts != null); Bpl.Type/*!*/ ty;
Type(out ty);
ts.Add(ty);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
Type(out ty);
ts.Add(ty);
@@ -763,21 +765,21 @@ private class BvBounds : Expr {
Parents = null;
bool u;
IToken/*!*/ parent;
- Expect(21);
+ Expect(23);
Parents = new List<ConstantParent/*!*/> ();
u = false;
- if (la.kind == 1 || la.kind == 20) {
- if (la.kind == 20) {
+ if (la.kind == 1 || la.kind == 22) {
+ if (la.kind == 22) {
Get();
u = true;
}
Ident(out parent);
Parents.Add(new ConstantParent (
new IdentifierExpr(parent, parent.val), u));
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
u = false;
- if (la.kind == 20) {
+ if (la.kind == 22) {
Get();
u = true;
}
@@ -786,7 +788,7 @@ private class BvBounds : Expr {
new IdentifierExpr(parent, parent.val), u));
}
}
- if (la.kind == 22) {
+ if (la.kind == 24) {
Get();
ChildrenComplete = true;
}
@@ -796,7 +798,7 @@ private class BvBounds : Expr {
Contract.Ensures(Contract.ValueAtReturn(out tyd) != null); string/*!*/ varName = ""; Bpl.Type/*!*/ ty; IToken/*!*/ tok;
Type(out ty);
tok = ty.tok;
- if (la.kind == 10) {
+ if (la.kind == 11) {
Get();
if (ty is UnresolvedTypeIdentifier &&
cce.NonNull(ty as UnresolvedTypeIdentifier).Arguments.Length == 0) {
@@ -822,7 +824,7 @@ private class BvBounds : Expr {
if (la.kind == 1) {
WhiteSpaceIdents(out paramTokens);
}
- if (la.kind == 29) {
+ if (la.kind == 31) {
Get();
Type(out body);
synonym = true;
@@ -854,15 +856,15 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
Contract.Ensures(Contract.ValueAtReturn(out name) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ins) != null); Contract.Ensures(Contract.ValueAtReturn(out outs) != null);
IToken/*!*/ typeParamTok; typeParams = new TypeVariableSeq();
outs = new VariableSeq(); kv = null;
- while (la.kind == 25) {
+ while (la.kind == 27) {
Attribute(ref kv);
}
Ident(out name);
- if (la.kind == 17) {
+ if (la.kind == 19) {
TypeParams(out typeParamTok, out typeParams);
}
ProcFormals(true, allowWhereClausesOnFormals, out ins);
- if (la.kind == 24) {
+ if (la.kind == 26) {
Get();
ProcFormals(false, allowWhereClausesOnFormals, out outs);
}
@@ -870,7 +872,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
void Spec(RequiresSeq/*!*/ pre, IdentifierExprSeq/*!*/ mods, EnsuresSeq/*!*/ post) {
Contract.Requires(pre != null); Contract.Requires(mods != null); Contract.Requires(post != null); TokenSeq/*!*/ ms;
- if (la.kind == 32) {
+ if (la.kind == 34) {
Get();
if (la.kind == 1) {
Idents(out ms);
@@ -880,19 +882,19 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
}
}
- Expect(7);
- } else if (la.kind == 33) {
+ Expect(8);
+ } else if (la.kind == 35) {
Get();
SpecPrePost(true, pre, post);
- } else if (la.kind == 34 || la.kind == 35) {
+ } else if (la.kind == 36 || la.kind == 37) {
SpecPrePost(false, pre, post);
- } else SynErr(95);
+ } else SynErr(99);
}
void ImplBody(out VariableSeq/*!*/ locals, out StmtList/*!*/ stmtList) {
Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); locals = new VariableSeq();
- Expect(25);
- while (la.kind == 6) {
+ Expect(27);
+ while (la.kind == 7) {
LocalVars(locals);
}
StmtList(out stmtList);
@@ -900,25 +902,25 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
void SpecPrePost(bool free, RequiresSeq/*!*/ pre, EnsuresSeq/*!*/ post) {
Contract.Requires(pre != null); Contract.Requires(post != null); Expr/*!*/ e; Token tok = null; QKeyValue kv = null;
- if (la.kind == 34) {
+ if (la.kind == 36) {
Get();
tok = t;
- while (la.kind == 25) {
+ while (la.kind == 27) {
Attribute(ref kv);
}
Proposition(out e);
- Expect(7);
+ Expect(8);
pre.Add(new Requires(tok, free, e, null, kv));
- } else if (la.kind == 35) {
+ } else if (la.kind == 37) {
Get();
tok = t;
- while (la.kind == 25) {
+ while (la.kind == 27) {
Attribute(ref kv);
}
Proposition(out e);
- Expect(7);
+ Expect(8);
post.Add(new Ensures(tok, free, e, null, kv));
- } else SynErr(96);
+ } else SynErr(100);
}
void StmtList(out StmtList/*!*/ stmtList) {
@@ -931,8 +933,8 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
StructuredCmd ec = null; StructuredCmd/*!*/ ecn;
TransferCmd tc = null; TransferCmd/*!*/ tcn;
- while (StartOf(5)) {
- if (StartOf(6)) {
+ while (StartOf(6)) {
+ if (StartOf(7)) {
LabelOrCmd(out c, out label);
if (c != null) {
// LabelOrCmd read a Cmd
@@ -955,7 +957,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
cs = new CmdSeq();
}
- } else if (la.kind == 38 || la.kind == 40 || la.kind == 43) {
+ } else if (la.kind == 40 || la.kind == 42 || la.kind == 45) {
StructuredCmd(out ecn);
ec = ecn;
if (startToken == null) { startToken = ec.tok; cs = new CmdSeq(); }
@@ -975,7 +977,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
}
}
- Expect(26);
+ Expect(28);
IToken/*!*/ endCurly = t;
if (startToken == null && bigblocks.Count == 0) {
startToken = t; cs = new CmdSeq();
@@ -1000,29 +1002,29 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
if (la.kind == 1) {
LabelOrAssign(out c, out label);
- } else if (la.kind == 44) {
+ } else if (la.kind == 46) {
Get();
x = t;
- while (la.kind == 25) {
+ while (la.kind == 27) {
Attribute(ref kv);
}
Proposition(out e);
c = new AssertCmd(x, e, kv);
- Expect(7);
- } else if (la.kind == 45) {
+ Expect(8);
+ } else if (la.kind == 47) {
Get();
x = t;
- while (la.kind == 25) {
+ while (la.kind == 27) {
Attribute(ref kv);
}
Proposition(out e);
c = new AssumeCmd(x, e, kv);
- Expect(7);
- } else if (la.kind == 46) {
+ Expect(8);
+ } else if (la.kind == 48) {
Get();
x = t;
Idents(out xs);
- Expect(7);
+ Expect(8);
ids = new IdentifierExprSeq();
foreach(IToken/*!*/ y in xs){
Contract.Assert(y != null);
@@ -1030,27 +1032,27 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
}
c = new HavocCmd(x,ids);
- } else if (la.kind == 33 || la.kind == 48) {
+ } else if (la.kind == 35 || la.kind == 50) {
CallCmd(out cn);
- Expect(7);
+ Expect(8);
c = cn;
- } else SynErr(97);
+ } else SynErr(101);
}
void StructuredCmd(out StructuredCmd/*!*/ ec) {
Contract.Ensures(Contract.ValueAtReturn(out ec) != null); ec = dummyStructuredCmd; Contract.Assume(cce.IsPeerConsistent(ec));
IfCmd/*!*/ ifcmd; WhileCmd/*!*/ wcmd; BreakCmd/*!*/ bcmd;
- if (la.kind == 38) {
+ if (la.kind == 40) {
IfCmd(out ifcmd);
ec = ifcmd;
- } else if (la.kind == 40) {
+ } else if (la.kind == 42) {
WhileCmd(out wcmd);
ec = wcmd;
- } else if (la.kind == 43) {
+ } else if (la.kind == 45) {
BreakCmd(out bcmd);
ec = bcmd;
- } else SynErr(98);
+ } else SynErr(102);
}
void TransferCmd(out TransferCmd/*!*/ tc) {
@@ -1058,7 +1060,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
Token y; TokenSeq/*!*/ xs;
StringSeq ss = new StringSeq();
- if (la.kind == 36) {
+ if (la.kind == 38) {
Get();
y = t;
Idents(out xs);
@@ -1067,11 +1069,11 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
ss.Add(s.val); }
tc = new GotoCmd(y, ss);
- } else if (la.kind == 37) {
+ } else if (la.kind == 39) {
Get();
tc = new ReturnCmd(t);
- } else SynErr(99);
- Expect(7);
+ } else SynErr(103);
+ Expect(8);
}
void IfCmd(out IfCmd/*!*/ ifcmd) {
@@ -1081,21 +1083,21 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
IfCmd/*!*/ elseIf; IfCmd elseIfOption = null;
StmtList/*!*/ els; StmtList elseOption = null;
- Expect(38);
+ Expect(40);
x = t;
Guard(out guard);
- Expect(25);
+ Expect(27);
StmtList(out thn);
- if (la.kind == 39) {
+ if (la.kind == 41) {
Get();
- if (la.kind == 38) {
+ if (la.kind == 40) {
IfCmd(out elseIf);
elseIfOption = elseIf;
- } else if (la.kind == 25) {
+ } else if (la.kind == 27) {
Get();
StmtList(out els);
elseOption = els;
- } else SynErr(100);
+ } else SynErr(104);
}
ifcmd = new IfCmd(x, guard, thn, elseIfOption, elseOption);
}
@@ -1107,18 +1109,18 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
StmtList/*!*/ body;
QKeyValue kv = null;
- Expect(40);
+ Expect(42);
x = t;
Guard(out guard);
Contract.Assume(guard == null || cce.Owner.None(guard));
- while (la.kind == 33 || la.kind == 41) {
+ while (la.kind == 35 || la.kind == 43) {
isFree = false; z = la/*lookahead token*/;
- if (la.kind == 33) {
+ if (la.kind == 35) {
Get();
isFree = true;
}
- Expect(41);
- while (la.kind == 25) {
+ Expect(43);
+ while (la.kind == 27) {
Attribute(ref kv);
}
Expression(out e);
@@ -1128,9 +1130,9 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
invariants.Add(new AssertCmd(z, e, kv));
}
- Expect(7);
+ Expect(8);
}
- Expect(25);
+ Expect(27);
StmtList(out body);
wcmd = new WhileCmd(x, guard, invariants, body);
}
@@ -1139,27 +1141,27 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
Contract.Ensures(Contract.ValueAtReturn(out bcmd) != null); IToken/*!*/ x; IToken/*!*/ y;
string breakLabel = null;
- Expect(43);
+ Expect(45);
x = t;
if (la.kind == 1) {
Ident(out y);
breakLabel = y.val;
}
- Expect(7);
+ Expect(8);
bcmd = new BreakCmd(x, breakLabel);
}
void Guard(out Expr e) {
Expr/*!*/ ee; e = null;
- Expect(8);
- if (la.kind == 42) {
+ Expect(9);
+ if (la.kind == 44) {
Get();
e = null;
- } else if (StartOf(7)) {
+ } else if (StartOf(8)) {
Expression(out ee);
e = ee;
- } else SynErr(101);
- Expect(9);
+ } else SynErr(105);
+ Expect(10);
}
void LabelOrAssign(out Cmd c, out IToken label) {
@@ -1172,40 +1174,40 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
Ident(out id);
x = t;
- if (la.kind == 10) {
+ if (la.kind == 11) {
Get();
c = null; label = x;
- } else if (la.kind == 11 || la.kind == 15 || la.kind == 47) {
+ } else if (la.kind == 12 || la.kind == 17 || la.kind == 49) {
lhss = new List<AssignLhs/*!*/>();
lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val));
- while (la.kind == 15) {
+ while (la.kind == 17) {
MapAssignIndex(out y, out indexes);
lhs = new MapAssignLhs(y, lhs, indexes);
}
lhss.Add(lhs);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
Ident(out id);
lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val));
- while (la.kind == 15) {
+ while (la.kind == 17) {
MapAssignIndex(out y, out indexes);
lhs = new MapAssignLhs(y, lhs, indexes);
}
lhss.Add(lhs);
}
- Expect(47);
+ Expect(49);
x = t; /* use location of := */
Expression(out e0);
rhss = new List<Expr/*!*/> ();
rhss.Add(e0);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
Expression(out e0);
rhss.Add(e0);
}
- Expect(7);
+ Expect(8);
c = new AssignCmd(x, lhss, rhss);
- } else SynErr(102);
+ } else SynErr(106);
}
void CallCmd(out Cmd/*!*/ c) {
@@ -1217,33 +1219,33 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
c = dummyCmd;
bool isFree = false;
- if (la.kind == 33) {
+ if (la.kind == 35) {
Get();
isFree = true;
}
- Expect(48);
+ Expect(50);
x = t;
- while (la.kind == 25) {
+ while (la.kind == 27) {
Attribute(ref kv);
}
if (la.kind == 1) {
Ident(out first);
- if (la.kind == 8) {
+ if (la.kind == 9) {
Get();
- if (StartOf(8)) {
+ if (StartOf(9)) {
CallForallArg(out en);
es.Add(en);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
CallForallArg(out en);
es.Add(en);
}
}
- Expect(9);
+ Expect(10);
c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree;
- } else if (la.kind == 11 || la.kind == 47) {
+ } else if (la.kind == 12 || la.kind == 49) {
ids.Add(new IdentifierExpr(first, first.val));
- if (la.kind == 11) {
+ if (la.kind == 12) {
Get();
CallOutIdent(out p);
if (p==null) {
@@ -1252,7 +1254,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
ids.Add(new IdentifierExpr(p, p.val));
}
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
CallOutIdent(out p);
if (p==null) {
@@ -1263,41 +1265,41 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
}
}
- Expect(47);
+ Expect(49);
Ident(out first);
- Expect(8);
- if (StartOf(8)) {
+ Expect(9);
+ if (StartOf(9)) {
CallForallArg(out en);
es.Add(en);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
CallForallArg(out en);
es.Add(en);
}
}
- Expect(9);
+ Expect(10);
c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree;
- } else SynErr(103);
- } else if (la.kind == 49) {
+ } else SynErr(107);
+ } else if (la.kind == 51) {
Get();
Ident(out first);
- Expect(8);
+ Expect(9);
args = new List<Expr>();
- if (StartOf(8)) {
+ if (StartOf(9)) {
CallForallArg(out en);
args.Add(en);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
CallForallArg(out en);
args.Add(en);
}
}
- Expect(9);
+ Expect(10);
c = new CallForallCmd(x, first.val, args, kv); ((CallForallCmd) c).IsFree = isFree;
- } else if (la.kind == 42) {
+ } else if (la.kind == 44) {
Get();
ids.Add(null);
- if (la.kind == 11) {
+ if (la.kind == 12) {
Get();
CallOutIdent(out p);
if (p==null) {
@@ -1306,7 +1308,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
ids.Add(new IdentifierExpr(p, p.val));
}
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
CallOutIdent(out p);
if (p==null) {
@@ -1317,70 +1319,70 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
}
}
- Expect(47);
+ Expect(49);
Ident(out first);
- Expect(8);
- if (StartOf(8)) {
+ Expect(9);
+ if (StartOf(9)) {
CallForallArg(out en);
es.Add(en);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
CallForallArg(out en);
es.Add(en);
}
}
- Expect(9);
+ Expect(10);
c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree;
- } else SynErr(104);
+ } else SynErr(108);
}
void MapAssignIndex(out IToken/*!*/ x, out List<Expr/*!*/>/*!*/ indexes) {
Contract.Ensures(Contract.ValueAtReturn(out x) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out indexes))); indexes = new List<Expr/*!*/> ();
Expr/*!*/ e;
- Expect(15);
+ Expect(17);
x = t;
- if (StartOf(7)) {
+ if (StartOf(8)) {
Expression(out e);
indexes.Add(e);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
Expression(out e);
indexes.Add(e);
}
}
- Expect(16);
+ Expect(18);
}
void CallForallArg(out Expr exprOptional) {
exprOptional = null;
Expr/*!*/ e;
- if (la.kind == 42) {
+ if (la.kind == 44) {
Get();
- } else if (StartOf(7)) {
+ } else if (StartOf(8)) {
Expression(out e);
exprOptional = e;
- } else SynErr(105);
+ } else SynErr(109);
}
void CallOutIdent(out IToken id) {
id = null;
IToken/*!*/ p;
- if (la.kind == 42) {
+ if (la.kind == 44) {
Get();
} else if (la.kind == 1) {
Ident(out p);
id = p;
- } else SynErr(106);
+ } else SynErr(110);
}
void Expressions(out ExprSeq/*!*/ es) {
Contract.Ensures(Contract.ValueAtReturn(out es) != null); Expr/*!*/ e; es = new ExprSeq();
Expression(out e);
es.Add(e);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
Expression(out e);
es.Add(e);
@@ -1390,8 +1392,8 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
void ImpliesExpression(bool noExplies, out Expr/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
LogicalExpression(out e0);
- if (StartOf(9)) {
- if (la.kind == 52 || la.kind == 53) {
+ if (StartOf(10)) {
+ if (la.kind == 54 || la.kind == 55) {
ImpliesOp();
x = t;
ImpliesExpression(true, out e1);
@@ -1403,7 +1405,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
x = t;
LogicalExpression(out e1);
e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0);
- while (la.kind == 54 || la.kind == 55) {
+ while (la.kind == 56 || la.kind == 57) {
ExpliesOp();
x = t;
LogicalExpression(out e1);
@@ -1414,23 +1416,23 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
}
void EquivOp() {
- if (la.kind == 50) {
+ if (la.kind == 52) {
Get();
- } else if (la.kind == 51) {
+ } else if (la.kind == 53) {
Get();
- } else SynErr(107);
+ } else SynErr(111);
}
void LogicalExpression(out Expr/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
RelationalExpression(out e0);
- if (StartOf(10)) {
- if (la.kind == 56 || la.kind == 57) {
+ if (StartOf(11)) {
+ if (la.kind == 58 || la.kind == 59) {
AndOp();
x = t;
RelationalExpression(out e1);
e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1);
- while (la.kind == 56 || la.kind == 57) {
+ while (la.kind == 58 || la.kind == 59) {
AndOp();
x = t;
RelationalExpression(out e1);
@@ -1441,7 +1443,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
x = t;
RelationalExpression(out e1);
e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1);
- while (la.kind == 58 || la.kind == 59) {
+ while (la.kind == 60 || la.kind == 61) {
OrOp();
x = t;
RelationalExpression(out e1);
@@ -1452,25 +1454,25 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
}
void ImpliesOp() {
- if (la.kind == 52) {
+ if (la.kind == 54) {
Get();
- } else if (la.kind == 53) {
+ } else if (la.kind == 55) {
Get();
- } else SynErr(108);
+ } else SynErr(112);
}
void ExpliesOp() {
- if (la.kind == 54) {
+ if (la.kind == 56) {
Get();
- } else if (la.kind == 55) {
+ } else if (la.kind == 57) {
Get();
- } else SynErr(109);
+ } else SynErr(113);
}
void RelationalExpression(out Expr/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op;
BvTerm(out e0);
- if (StartOf(11)) {
+ if (StartOf(12)) {
RelOp(out x, out op);
BvTerm(out e1);
e0 = Expr.Binary(x, op, e0, e1);
@@ -1478,25 +1480,25 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
}
void AndOp() {
- if (la.kind == 56) {
+ if (la.kind == 58) {
Get();
- } else if (la.kind == 57) {
+ } else if (la.kind == 59) {
Get();
- } else SynErr(110);
+ } else SynErr(114);
}
void OrOp() {
- if (la.kind == 58) {
+ if (la.kind == 60) {
Get();
- } else if (la.kind == 59) {
+ } else if (la.kind == 61) {
Get();
- } else SynErr(111);
+ } else SynErr(115);
}
void BvTerm(out Expr/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
Term(out e0);
- while (la.kind == 68) {
+ while (la.kind == 70) {
Get();
x = t;
Term(out e1);
@@ -1507,64 +1509,64 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
void RelOp(out IToken/*!*/ x, out BinaryOperator.Opcode op) {
Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
switch (la.kind) {
- case 60: {
+ case 62: {
Get();
x = t; op=BinaryOperator.Opcode.Eq;
break;
}
- case 17: {
+ case 19: {
Get();
x = t; op=BinaryOperator.Opcode.Lt;
break;
}
- case 18: {
+ case 20: {
Get();
x = t; op=BinaryOperator.Opcode.Gt;
break;
}
- case 61: {
+ case 63: {
Get();
x = t; op=BinaryOperator.Opcode.Le;
break;
}
- case 62: {
+ case 64: {
Get();
x = t; op=BinaryOperator.Opcode.Ge;
break;
}
- case 63: {
+ case 65: {
Get();
x = t; op=BinaryOperator.Opcode.Neq;
break;
}
- case 64: {
+ case 66: {
Get();
x = t; op=BinaryOperator.Opcode.Subtype;
break;
}
- case 65: {
+ case 67: {
Get();
x = t; op=BinaryOperator.Opcode.Neq;
break;
}
- case 66: {
+ case 68: {
Get();
x = t; op=BinaryOperator.Opcode.Le;
break;
}
- case 67: {
+ case 69: {
Get();
x = t; op=BinaryOperator.Opcode.Ge;
break;
}
- default: SynErr(112); break;
+ default: SynErr(116); break;
}
}
void Term(out Expr/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op;
Factor(out e0);
- while (la.kind == 69 || la.kind == 70) {
+ while (la.kind == 71 || la.kind == 72) {
AddOp(out x, out op);
Factor(out e1);
e0 = Expr.Binary(x, op, e0, e1);
@@ -1573,64 +1575,78 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
void Factor(out Expr/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op;
- UnaryExpression(out e0);
- while (la.kind == 42 || la.kind == 71 || la.kind == 72) {
+ Power(out e0);
+ while (StartOf(13)) {
MulOp(out x, out op);
- UnaryExpression(out e1);
+ Power(out e1);
e0 = Expr.Binary(x, op, e0, e1);
}
}
void AddOp(out IToken/*!*/ x, out BinaryOperator.Opcode op) {
Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
- if (la.kind == 69) {
+ if (la.kind == 71) {
Get();
x = t; op=BinaryOperator.Opcode.Add;
- } else if (la.kind == 70) {
+ } else if (la.kind == 72) {
Get();
x = t; op=BinaryOperator.Opcode.Sub;
- } else SynErr(113);
+ } else SynErr(117);
}
- void UnaryExpression(out Expr/*!*/ e) {
- Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
- e = dummyExpr;
-
- if (la.kind == 70) {
+ void Power(out Expr/*!*/ e0) {
+ Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
+ UnaryExpression(out e0);
+ if (la.kind == 76) {
Get();
x = t;
- UnaryExpression(out e);
- e = Expr.Binary(x, BinaryOperator.Opcode.Sub, new LiteralExpr(x, BigNum.ZERO), e);
- } else if (la.kind == 73 || la.kind == 74) {
- NegOp();
- x = t;
- UnaryExpression(out e);
- e = Expr.Unary(x, UnaryOperator.Opcode.Not, e);
- } else if (StartOf(12)) {
- CoercionExpression(out e);
- } else SynErr(114);
+ Power(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Pow, e0, e1);
+ }
}
void MulOp(out IToken/*!*/ x, out BinaryOperator.Opcode op) {
Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
- if (la.kind == 42) {
+ if (la.kind == 44) {
Get();
x = t; op=BinaryOperator.Opcode.Mul;
- } else if (la.kind == 71) {
+ } else if (la.kind == 73) {
Get();
x = t; op=BinaryOperator.Opcode.Div;
- } else if (la.kind == 72) {
+ } else if (la.kind == 74) {
Get();
x = t; op=BinaryOperator.Opcode.Mod;
- } else SynErr(115);
+ } else if (la.kind == 75) {
+ Get();
+ x = t; op=BinaryOperator.Opcode.RealDiv;
+ } else SynErr(118);
+ }
+
+ void UnaryExpression(out Expr/*!*/ e) {
+ Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
+ e = dummyExpr;
+
+ if (la.kind == 72) {
+ Get();
+ x = t;
+ UnaryExpression(out e);
+ e = Expr.Unary(x, UnaryOperator.Opcode.Neg, e);
+ } else if (la.kind == 77 || la.kind == 78) {
+ NegOp();
+ x = t;
+ UnaryExpression(out e);
+ e = Expr.Unary(x, UnaryOperator.Opcode.Not, e);
+ } else if (StartOf(14)) {
+ CoercionExpression(out e);
+ } else SynErr(119);
}
void NegOp() {
- if (la.kind == 73) {
+ if (la.kind == 77) {
Get();
- } else if (la.kind == 74) {
+ } else if (la.kind == 78) {
Get();
- } else SynErr(116);
+ } else SynErr(120);
}
void CoercionExpression(out Expr/*!*/ e) {
@@ -1639,7 +1655,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
BigNum bn;
ArrayExpression(out e);
- while (la.kind == 10) {
+ while (la.kind == 11) {
Get();
x = t;
if (StartOf(2)) {
@@ -1654,7 +1670,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
e = new BvBounds(x, bn, ((LiteralExpr)e).asBigNum);
}
- } else SynErr(117);
+ } else SynErr(121);
}
}
@@ -1665,20 +1681,20 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
ExprSeq/*!*/ allArgs = dummyExprSeq;
AtomExpression(out e);
- while (la.kind == 15) {
+ while (la.kind == 17) {
Get();
x = t; allArgs = new ExprSeq ();
allArgs.Add(e);
store = false; bvExtract = false;
- if (StartOf(13)) {
- if (StartOf(7)) {
+ if (StartOf(15)) {
+ if (StartOf(8)) {
Expression(out index0);
if (index0 is BvBounds)
bvExtract = true;
else
allArgs.Add(index0);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
Expression(out e1);
if (bvExtract || e1 is BvBounds)
@@ -1686,7 +1702,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
allArgs.Add(e1);
}
- if (la.kind == 47) {
+ if (la.kind == 49) {
Get();
Expression(out e1);
if (bvExtract || e1 is BvBounds)
@@ -1700,7 +1716,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
allArgs.Add(e1); store = true;
}
}
- Expect(16);
+ Expect(18);
if (store)
e = new NAryExpr(x, new MapStore(x, allArgs.Length - 2), allArgs);
else if (bvExtract)
@@ -1725,7 +1741,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
}
void AtomExpression(out Expr/*!*/ e) {
- Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn;
+ Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn; BigDec bd;
ExprSeq/*!*/ es; VariableSeq/*!*/ ds; Trigger trig;
TypeVariableSeq/*!*/ typeParams;
IdentifierExpr/*!*/ id;
@@ -1735,12 +1751,12 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
List<Block/*!*/>/*!*/ blocks;
switch (la.kind) {
- case 75: {
+ case 79: {
Get();
e = new LiteralExpr(t, false);
break;
}
- case 76: {
+ case 80: {
Get();
e = new LiteralExpr(t, true);
break;
@@ -1750,6 +1766,11 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
e = new LiteralExpr(t, bn);
break;
}
+ case 5: case 6: {
+ Dec(out bd);
+ e = new LiteralExpr(t, bd);
+ break;
+ }
case 2: {
BvLit(out bn, out n);
e = new LiteralExpr(t, bn, n);
@@ -1758,47 +1779,65 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
case 1: {
Ident(out x);
id = new IdentifierExpr(x, x.val); e = id;
- if (la.kind == 8) {
+ if (la.kind == 9) {
Get();
- if (StartOf(7)) {
+ if (StartOf(8)) {
Expressions(out es);
e = new NAryExpr(x, new FunctionCall(id), es);
- } else if (la.kind == 9) {
+ } else if (la.kind == 10) {
e = new NAryExpr(x, new FunctionCall(id), new ExprSeq());
- } else SynErr(118);
- Expect(9);
+ } else SynErr(122);
+ Expect(10);
}
break;
}
- case 77: {
+ case 81: {
Get();
x = t;
- Expect(8);
- Expression(out e);
Expect(9);
+ Expression(out e);
+ Expect(10);
e = new OldExpr(x, e);
break;
}
- case 8: {
+ case 14: {
Get();
- if (StartOf(7)) {
+ x = t;
+ Expect(9);
+ Expression(out e);
+ Expect(10);
+ e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToInt), new ExprSeq(e));
+ break;
+ }
+ case 15: {
+ Get();
+ x = t;
+ Expect(9);
+ Expression(out e);
+ Expect(10);
+ e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToReal), new ExprSeq(e));
+ break;
+ }
+ case 9: {
+ Get();
+ if (StartOf(8)) {
Expression(out e);
if (e is BvBounds)
this.SemErr("parentheses around bitvector bounds " +
"are not allowed");
- } else if (la.kind == 49 || la.kind == 81) {
+ } else if (la.kind == 51 || la.kind == 85) {
Forall();
x = t;
QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e);
if (typeParams.Length + ds.Length > 0)
e = new ForallExpr(x, typeParams, ds, kv, trig, e);
- } else if (la.kind == 82 || la.kind == 83) {
+ } else if (la.kind == 86 || la.kind == 87) {
Exists();
x = t;
QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e);
if (typeParams.Length + ds.Length > 0)
e = new ExistsExpr(x, typeParams, ds, kv, trig, e);
- } else if (la.kind == 84 || la.kind == 85) {
+ } else if (la.kind == 88 || la.kind == 89) {
Lambda();
x = t;
QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e);
@@ -1806,21 +1845,39 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
SemErr("triggers not allowed in lambda expressions");
if (typeParams.Length + ds.Length > 0)
e = new LambdaExpr(x, typeParams, ds, kv, e);
- } else SynErr(119);
- Expect(9);
+ } else SynErr(123);
+ Expect(10);
break;
}
- case 38: {
+ case 40: {
IfThenElseExpression(out e);
break;
}
- case 78: {
+ case 82: {
CodeExpression(out locals, out blocks);
e = new CodeExpr(locals, blocks);
break;
}
- default: SynErr(120); break;
+ default: SynErr(124); break;
+ }
+ }
+
+ void Dec(out BigDec n) {
+ string s = "";
+ if (la.kind == 5) {
+ Get();
+ s = t.val;
+ } else if (la.kind == 6) {
+ Get();
+ s = t.val;
+ } else SynErr(125);
+ try {
+ n = BigDec.FromString(s);
+ } catch (FormatException) {
+ this.SemErr("incorrectly formatted number");
+ n = BigDec.ZERO;
}
+
}
void BvLit(out BigNum n, out int m) {
@@ -1840,11 +1897,11 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
}
void Forall() {
- if (la.kind == 49) {
+ if (la.kind == 51) {
Get();
- } else if (la.kind == 81) {
+ } else if (la.kind == 85) {
Get();
- } else SynErr(121);
+ } else SynErr(126);
}
void QuantifierBody(IToken/*!*/ q, out TypeVariableSeq/*!*/ typeParams, out VariableSeq/*!*/ ds,
@@ -1855,35 +1912,35 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
kv = null;
ds = new VariableSeq ();
- if (la.kind == 17) {
+ if (la.kind == 19) {
TypeParams(out tok, out typeParams);
if (la.kind == 1) {
BoundVars(q, out ds);
}
} else if (la.kind == 1) {
BoundVars(q, out ds);
- } else SynErr(122);
+ } else SynErr(127);
QSep();
- while (la.kind == 25) {
+ while (la.kind == 27) {
AttributeOrTrigger(ref kv, ref trig);
}
Expression(out body);
}
void Exists() {
- if (la.kind == 82) {
+ if (la.kind == 86) {
Get();
- } else if (la.kind == 83) {
+ } else if (la.kind == 87) {
Get();
- } else SynErr(123);
+ } else SynErr(128);
}
void Lambda() {
- if (la.kind == 84) {
+ if (la.kind == 88) {
Get();
- } else if (la.kind == 85) {
+ } else if (la.kind == 89) {
Get();
- } else SynErr(124);
+ } else SynErr(129);
}
void IfThenElseExpression(out Expr/*!*/ e) {
@@ -1891,12 +1948,12 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
IToken/*!*/ tok;
Expr/*!*/ e0, e1, e2;
e = dummyExpr;
- Expect(38);
+ Expect(40);
tok = t;
Expression(out e0);
- Expect(80);
+ Expect(84);
Expression(out e1);
- Expect(39);
+ Expect(41);
Expression(out e2);
e = new NAryExpr(tok, new IfThenElse(tok), new ExprSeq(e0, e1, e2));
}
@@ -1905,8 +1962,8 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out blocks))); locals = new VariableSeq(); Block/*!*/ b;
blocks = new List<Block/*!*/>();
- Expect(78);
- while (la.kind == 6) {
+ Expect(82);
+ while (la.kind == 7) {
LocalVars(locals);
}
SpecBlock(out b);
@@ -1915,7 +1972,7 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
SpecBlock(out b);
blocks.Add(b);
}
- Expect(79);
+ Expect(83);
}
void SpecBlock(out Block/*!*/ b) {
@@ -1928,8 +1985,8 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
Expr/*!*/ e;
Ident(out x);
- Expect(10);
- while (StartOf(6)) {
+ Expect(11);
+ while (StartOf(7)) {
LabelOrCmd(out c, out label);
if (c != null) {
Contract.Assert(label == null);
@@ -1940,7 +1997,7 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
}
}
- if (la.kind == 36) {
+ if (la.kind == 38) {
Get();
y = t;
Idents(out xs);
@@ -1949,12 +2006,12 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
ss.Add(s.val); }
b = new Block(x,x.val,cs,new GotoCmd(y,ss));
- } else if (la.kind == 37) {
+ } else if (la.kind == 39) {
Get();
Expression(out e);
b = new Block(x,x.val,cs,new ReturnExprCmd(t,e));
- } else SynErr(125);
- Expect(7);
+ } else SynErr(130);
+ Expect(8);
}
void AttributeOrTrigger(ref QKeyValue kv, ref Trigger trig) {
@@ -1962,16 +2019,16 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
string key;
List<object/*!*/> parameters; object/*!*/ param;
- Expect(25);
+ Expect(27);
tok = t;
- if (la.kind == 10) {
+ if (la.kind == 11) {
Get();
Expect(1);
key = t.val; parameters = new List<object/*!*/>();
- if (StartOf(14)) {
+ if (StartOf(16)) {
AttributeParameter(out param);
parameters.Add(param);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
AttributeParameter(out param);
parameters.Add(param);
@@ -1996,10 +2053,10 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
}
}
- } else if (StartOf(7)) {
+ } else if (StartOf(8)) {
Expression(out e);
es = new ExprSeq(e);
- while (la.kind == 11) {
+ while (la.kind == 12) {
Get();
Expression(out e);
es.Add(e);
@@ -2010,8 +2067,8 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
trig.AddLast(new Trigger(tok, true, es, null));
}
- } else SynErr(126);
- Expect(26);
+ } else SynErr(131);
+ Expect(28);
}
void AttributeParameter(out object/*!*/ o) {
@@ -2022,18 +2079,18 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
if (la.kind == 4) {
Get();
o = t.val.Substring(1, t.val.Length-2);
- } else if (StartOf(7)) {
+ } else if (StartOf(8)) {
Expression(out e);
o = e;
- } else SynErr(127);
+ } else SynErr(132);
}
void QSep() {
- if (la.kind == 86) {
+ if (la.kind == 90) {
Get();
- } else if (la.kind == 87) {
+ } else if (la.kind == 91) {
Get();
- } else SynErr(128);
+ } else SynErr(133);
}
@@ -2049,21 +2106,23 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
}
static readonly bool[,]/*!*/ set = {
- {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,T, x,x,x,T, T,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,x,x, x,x,x,x, T,x,x,x, x,T,T,T, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, T,T,T,x, T,x,x,T, T,T,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, T,T,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,T, T,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x}
+ {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+ {x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,x,x, x,T,T,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+ {x,T,x,x, x,x,x,x, x,T,x,x, x,x,T,T, T,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+ {x,x,x,x, x,x,x,x, x,T,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+ {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,T,T, T,x,T,x, x,T,T,T, T,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+ {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,T,T, T,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+ {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x},
+ {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+ {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x},
+ {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x},
+ {x,T,T,T, T,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x}
};
} // end Parser
@@ -2093,130 +2152,135 @@ public class Errors {
case 2: s = "bvlit expected"; break;
case 3: s = "digits expected"; break;
case 4: s = "string expected"; break;
- case 5: s = "float expected"; break;
- case 6: s = "\"var\" expected"; break;
- case 7: s = "\";\" expected"; break;
- case 8: s = "\"(\" expected"; break;
- case 9: s = "\")\" expected"; break;
- case 10: s = "\":\" expected"; break;
- case 11: s = "\",\" expected"; break;
- case 12: s = "\"where\" expected"; break;
- case 13: s = "\"int\" expected"; break;
- case 14: s = "\"bool\" expected"; break;
- case 15: s = "\"[\" expected"; break;
- case 16: s = "\"]\" expected"; break;
- case 17: s = "\"<\" expected"; break;
- case 18: s = "\">\" expected"; break;
- case 19: s = "\"const\" expected"; break;
- case 20: s = "\"unique\" expected"; break;
- case 21: s = "\"extends\" expected"; break;
- case 22: s = "\"complete\" expected"; break;
- case 23: s = "\"function\" expected"; break;
- case 24: s = "\"returns\" expected"; break;
- case 25: s = "\"{\" expected"; break;
- case 26: s = "\"}\" expected"; break;
- case 27: s = "\"axiom\" expected"; break;
- case 28: s = "\"type\" expected"; break;
- case 29: s = "\"=\" expected"; break;
- case 30: s = "\"procedure\" expected"; break;
- case 31: s = "\"implementation\" expected"; break;
- case 32: s = "\"modifies\" expected"; break;
- case 33: s = "\"free\" expected"; break;
- case 34: s = "\"requires\" expected"; break;
- case 35: s = "\"ensures\" expected"; break;
- case 36: s = "\"goto\" expected"; break;
- case 37: s = "\"return\" expected"; break;
- case 38: s = "\"if\" expected"; break;
- case 39: s = "\"else\" expected"; break;
- case 40: s = "\"while\" expected"; break;
- case 41: s = "\"invariant\" expected"; break;
- case 42: s = "\"*\" expected"; break;
- case 43: s = "\"break\" expected"; break;
- case 44: s = "\"assert\" expected"; break;
- case 45: s = "\"assume\" expected"; break;
- case 46: s = "\"havoc\" expected"; break;
- case 47: s = "\":=\" expected"; break;
- case 48: s = "\"call\" expected"; break;
- case 49: s = "\"forall\" expected"; break;
- case 50: s = "\"<==>\" expected"; break;
- case 51: s = "\"\\u21d4\" expected"; break;
- case 52: s = "\"==>\" expected"; break;
- case 53: s = "\"\\u21d2\" expected"; break;
- case 54: s = "\"<==\" expected"; break;
- case 55: s = "\"\\u21d0\" expected"; break;
- case 56: s = "\"&&\" expected"; break;
- case 57: s = "\"\\u2227\" expected"; break;
- case 58: s = "\"||\" expected"; break;
- case 59: s = "\"\\u2228\" expected"; break;
- case 60: s = "\"==\" expected"; break;
- case 61: s = "\"<=\" expected"; break;
- case 62: s = "\">=\" expected"; break;
- case 63: s = "\"!=\" expected"; break;
- case 64: s = "\"<:\" expected"; break;
- case 65: s = "\"\\u2260\" expected"; break;
- case 66: s = "\"\\u2264\" expected"; break;
- case 67: s = "\"\\u2265\" expected"; break;
- case 68: s = "\"++\" expected"; break;
- case 69: s = "\"+\" expected"; break;
- case 70: s = "\"-\" expected"; break;
- case 71: s = "\"/\" expected"; break;
- case 72: s = "\"%\" expected"; break;
- case 73: s = "\"!\" expected"; break;
- case 74: s = "\"\\u00ac\" expected"; break;
- case 75: s = "\"false\" expected"; break;
- case 76: s = "\"true\" expected"; break;
- case 77: s = "\"old\" expected"; break;
- case 78: s = "\"|{\" expected"; break;
- case 79: s = "\"}|\" expected"; break;
- case 80: s = "\"then\" expected"; break;
- case 81: s = "\"\\u2200\" expected"; break;
- case 82: s = "\"exists\" expected"; break;
- case 83: s = "\"\\u2203\" expected"; break;
- case 84: s = "\"lambda\" expected"; break;
- case 85: s = "\"\\u03bb\" expected"; break;
- case 86: s = "\"::\" expected"; break;
- case 87: s = "\"\\u2022\" expected"; break;
- case 88: s = "??? expected"; break;
- case 89: s = "invalid Function"; break;
- case 90: s = "invalid Function"; break;
- case 91: s = "invalid Procedure"; break;
- case 92: s = "invalid Type"; break;
- case 93: s = "invalid TypeAtom"; break;
- case 94: s = "invalid TypeArgs"; break;
- case 95: s = "invalid Spec"; break;
- case 96: s = "invalid SpecPrePost"; break;
- case 97: s = "invalid LabelOrCmd"; break;
- case 98: s = "invalid StructuredCmd"; break;
- case 99: s = "invalid TransferCmd"; break;
- case 100: s = "invalid IfCmd"; break;
- case 101: s = "invalid Guard"; break;
- case 102: s = "invalid LabelOrAssign"; break;
- case 103: s = "invalid CallCmd"; break;
- case 104: s = "invalid CallCmd"; break;
- case 105: s = "invalid CallForallArg"; break;
- case 106: s = "invalid CallOutIdent"; break;
- case 107: s = "invalid EquivOp"; break;
- case 108: s = "invalid ImpliesOp"; break;
- case 109: s = "invalid ExpliesOp"; break;
- case 110: s = "invalid AndOp"; break;
- case 111: s = "invalid OrOp"; break;
- case 112: s = "invalid RelOp"; break;
- case 113: s = "invalid AddOp"; break;
- case 114: s = "invalid UnaryExpression"; break;
- case 115: s = "invalid MulOp"; break;
- case 116: s = "invalid NegOp"; break;
- case 117: s = "invalid CoercionExpression"; break;
- case 118: s = "invalid AtomExpression"; break;
- case 119: s = "invalid AtomExpression"; break;
- case 120: s = "invalid AtomExpression"; break;
- case 121: s = "invalid Forall"; break;
- case 122: s = "invalid QuantifierBody"; break;
- case 123: s = "invalid Exists"; break;
- case 124: s = "invalid Lambda"; break;
- case 125: s = "invalid SpecBlock"; break;
- case 126: s = "invalid AttributeOrTrigger"; break;
- case 127: s = "invalid AttributeParameter"; break;
- case 128: s = "invalid QSep"; break;
+ case 5: s = "decimal expected"; break;
+ case 6: s = "float expected"; break;
+ case 7: s = "\"var\" expected"; break;
+ case 8: s = "\";\" expected"; break;
+ case 9: s = "\"(\" expected"; break;
+ case 10: s = "\")\" expected"; break;
+ case 11: s = "\":\" expected"; break;
+ case 12: s = "\",\" expected"; break;
+ case 13: s = "\"where\" expected"; break;
+ case 14: s = "\"int\" expected"; break;
+ case 15: s = "\"real\" expected"; break;
+ case 16: s = "\"bool\" expected"; break;
+ case 17: s = "\"[\" expected"; break;
+ case 18: s = "\"]\" expected"; break;
+ case 19: s = "\"<\" expected"; break;
+ case 20: s = "\">\" expected"; break;
+ case 21: s = "\"const\" expected"; break;
+ case 22: s = "\"unique\" expected"; break;
+ case 23: s = "\"extends\" expected"; break;
+ case 24: s = "\"complete\" expected"; break;
+ case 25: s = "\"function\" expected"; break;
+ case 26: s = "\"returns\" expected"; break;
+ case 27: s = "\"{\" expected"; break;
+ case 28: s = "\"}\" expected"; break;
+ case 29: s = "\"axiom\" expected"; break;
+ case 30: s = "\"type\" expected"; break;
+ case 31: s = "\"=\" expected"; break;
+ case 32: s = "\"procedure\" expected"; break;
+ case 33: s = "\"implementation\" expected"; break;
+ case 34: s = "\"modifies\" expected"; break;
+ case 35: s = "\"free\" expected"; break;
+ case 36: s = "\"requires\" expected"; break;
+ case 37: s = "\"ensures\" expected"; break;
+ case 38: s = "\"goto\" expected"; break;
+ case 39: s = "\"return\" expected"; break;
+ case 40: s = "\"if\" expected"; break;
+ case 41: s = "\"else\" expected"; break;
+ case 42: s = "\"while\" expected"; break;
+ case 43: s = "\"invariant\" expected"; break;
+ case 44: s = "\"*\" expected"; break;
+ case 45: s = "\"break\" expected"; break;
+ case 46: s = "\"assert\" expected"; break;
+ case 47: s = "\"assume\" expected"; break;
+ case 48: s = "\"havoc\" expected"; break;
+ case 49: s = "\":=\" expected"; break;
+ case 50: s = "\"call\" expected"; break;
+ case 51: s = "\"forall\" expected"; break;
+ case 52: s = "\"<==>\" expected"; break;
+ case 53: s = "\"\\u21d4\" expected"; break;
+ case 54: s = "\"==>\" expected"; break;
+ case 55: s = "\"\\u21d2\" expected"; break;
+ case 56: s = "\"<==\" expected"; break;
+ case 57: s = "\"\\u21d0\" expected"; break;
+ case 58: s = "\"&&\" expected"; break;
+ case 59: s = "\"\\u2227\" expected"; break;
+ case 60: s = "\"||\" expected"; break;
+ case 61: s = "\"\\u2228\" expected"; break;
+ case 62: s = "\"==\" expected"; break;
+ case 63: s = "\"<=\" expected"; break;
+ case 64: s = "\">=\" expected"; break;
+ case 65: s = "\"!=\" expected"; break;
+ case 66: s = "\"<:\" expected"; break;
+ case 67: s = "\"\\u2260\" expected"; break;
+ case 68: s = "\"\\u2264\" expected"; break;
+ case 69: s = "\"\\u2265\" expected"; break;
+ case 70: s = "\"++\" expected"; break;
+ case 71: s = "\"+\" expected"; break;
+ case 72: s = "\"-\" expected"; break;
+ case 73: s = "\"div\" expected"; break;
+ case 74: s = "\"mod\" expected"; break;
+ case 75: s = "\"/\" expected"; break;
+ case 76: s = "\"**\" expected"; break;
+ case 77: s = "\"!\" expected"; break;
+ case 78: s = "\"\\u00ac\" expected"; break;
+ case 79: s = "\"false\" expected"; break;
+ case 80: s = "\"true\" expected"; break;
+ case 81: s = "\"old\" expected"; break;
+ case 82: s = "\"|{\" expected"; break;
+ case 83: s = "\"}|\" expected"; break;
+ case 84: s = "\"then\" expected"; break;
+ case 85: s = "\"\\u2200\" expected"; break;
+ case 86: s = "\"exists\" expected"; break;
+ case 87: s = "\"\\u2203\" expected"; break;
+ case 88: s = "\"lambda\" expected"; break;
+ case 89: s = "\"\\u03bb\" expected"; break;
+ case 90: s = "\"::\" expected"; break;
+ case 91: s = "\"\\u2022\" expected"; break;
+ case 92: s = "??? expected"; break;
+ case 93: s = "invalid Function"; break;
+ case 94: s = "invalid Function"; break;
+ case 95: s = "invalid Procedure"; break;
+ case 96: s = "invalid Type"; break;
+ case 97: s = "invalid TypeAtom"; break;
+ case 98: s = "invalid TypeArgs"; break;
+ case 99: s = "invalid Spec"; break;
+ case 100: s = "invalid SpecPrePost"; break;
+ case 101: s = "invalid LabelOrCmd"; break;
+ case 102: s = "invalid StructuredCmd"; break;
+ case 103: s = "invalid TransferCmd"; break;
+ case 104: s = "invalid IfCmd"; break;
+ case 105: s = "invalid Guard"; break;
+ case 106: s = "invalid LabelOrAssign"; break;
+ case 107: s = "invalid CallCmd"; break;
+ case 108: s = "invalid CallCmd"; break;
+ case 109: s = "invalid CallForallArg"; break;
+ case 110: s = "invalid CallOutIdent"; break;
+ case 111: s = "invalid EquivOp"; break;
+ case 112: s = "invalid ImpliesOp"; break;
+ case 113: s = "invalid ExpliesOp"; break;
+ case 114: s = "invalid AndOp"; break;
+ case 115: s = "invalid OrOp"; break;
+ case 116: s = "invalid RelOp"; break;
+ case 117: s = "invalid AddOp"; break;
+ case 118: s = "invalid MulOp"; break;
+ case 119: s = "invalid UnaryExpression"; break;
+ case 120: s = "invalid NegOp"; break;
+ case 121: s = "invalid CoercionExpression"; break;
+ case 122: s = "invalid AtomExpression"; break;
+ case 123: s = "invalid AtomExpression"; break;
+ case 124: s = "invalid AtomExpression"; break;
+ case 125: s = "invalid Dec"; break;
+ case 126: s = "invalid Forall"; break;
+ case 127: s = "invalid QuantifierBody"; break;
+ case 128: s = "invalid Exists"; break;
+ case 129: s = "invalid Lambda"; break;
+ case 130: s = "invalid SpecBlock"; break;
+ case 131: s = "invalid AttributeOrTrigger"; break;
+ case 132: s = "invalid AttributeParameter"; break;
+ case 133: s = "invalid QSep"; break;
default: s = "error " + n; break;
}
diff --git a/Source/Core/Scanner.cs b/Source/Core/Scanner.cs
index cfef86c7..60c15b41 100644
--- a/Source/Core/Scanner.cs
+++ b/Source/Core/Scanner.cs
@@ -211,8 +211,8 @@ public class UTF8Buffer: Buffer {
public class Scanner {
const char EOL = '\n';
const int eofSym = 0; /* pdt */
- const int maxT = 88;
- const int noSym = 88;
+ const int maxT = 92;
+ const int noSym = 92;
[ContractInvariantMethod]
@@ -256,42 +256,41 @@ public class Scanner {
for (int i = 65; i <= 90; ++i) start[i] = 2;
for (int i = 94; i <= 122; ++i) start[i] = 2;
for (int i = 126; i <= 126; ++i) start[i] = 2;
- for (int i = 48; i <= 57; ++i) start[i] = 9;
+ for (int i = 48; i <= 57; ++i) start[i] = 16;
for (int i = 34; i <= 34; ++i) start[i] = 6;
start[92] = 1;
- start[59] = 12;
- start[40] = 13;
- start[41] = 14;
- start[58] = 49;
- start[44] = 15;
- start[91] = 16;
- start[93] = 17;
- start[60] = 50;
- start[62] = 51;
- start[123] = 18;
- start[125] = 52;
- start[61] = 53;
- start[42] = 19;
- start[8660] = 22;
- start[8658] = 24;
- start[8656] = 25;
- start[38] = 26;
- start[8743] = 28;
- start[124] = 54;
- start[8744] = 30;
- start[33] = 55;
- start[8800] = 34;
- start[8804] = 35;
- start[8805] = 36;
- start[43] = 56;
- start[45] = 38;
- start[47] = 39;
- start[37] = 40;
- start[172] = 41;
- start[8704] = 44;
- start[8707] = 45;
- start[955] = 46;
- start[8226] = 48;
+ start[59] = 19;
+ start[40] = 20;
+ start[41] = 21;
+ start[58] = 55;
+ start[44] = 22;
+ start[91] = 23;
+ start[93] = 24;
+ start[60] = 56;
+ start[62] = 57;
+ start[123] = 25;
+ start[125] = 58;
+ start[61] = 59;
+ start[42] = 60;
+ start[8660] = 28;
+ start[8658] = 30;
+ start[8656] = 31;
+ start[38] = 32;
+ start[8743] = 34;
+ start[124] = 61;
+ start[8744] = 36;
+ start[33] = 62;
+ start[8800] = 40;
+ start[8804] = 41;
+ start[8805] = 42;
+ start[43] = 63;
+ start[45] = 44;
+ start[47] = 45;
+ start[172] = 47;
+ start[8704] = 50;
+ start[8707] = 51;
+ start[955] = 52;
+ start[8226] = 54;
start[Buffer.EOF] = -1;
}
@@ -489,42 +488,45 @@ public class Scanner {
void CheckLiteral() {
switch (t.val) {
- case "var": t.kind = 6; break;
- case "where": t.kind = 12; break;
- case "int": t.kind = 13; break;
- case "bool": t.kind = 14; break;
- case "const": t.kind = 19; break;
- case "unique": t.kind = 20; break;
- case "extends": t.kind = 21; break;
- case "complete": t.kind = 22; break;
- case "function": t.kind = 23; break;
- case "returns": t.kind = 24; break;
- case "axiom": t.kind = 27; break;
- case "type": t.kind = 28; break;
- case "procedure": t.kind = 30; break;
- case "implementation": t.kind = 31; break;
- case "modifies": t.kind = 32; break;
- case "free": t.kind = 33; break;
- case "requires": t.kind = 34; break;
- case "ensures": t.kind = 35; break;
- case "goto": t.kind = 36; break;
- case "return": t.kind = 37; break;
- case "if": t.kind = 38; break;
- case "else": t.kind = 39; break;
- case "while": t.kind = 40; break;
- case "invariant": t.kind = 41; break;
- case "break": t.kind = 43; break;
- case "assert": t.kind = 44; break;
- case "assume": t.kind = 45; break;
- case "havoc": t.kind = 46; break;
- case "call": t.kind = 48; break;
- case "forall": t.kind = 49; break;
- case "false": t.kind = 75; break;
- case "true": t.kind = 76; break;
- case "old": t.kind = 77; break;
- case "then": t.kind = 80; break;
- case "exists": t.kind = 82; break;
- case "lambda": t.kind = 84; break;
+ case "var": t.kind = 7; break;
+ case "where": t.kind = 13; break;
+ case "int": t.kind = 14; break;
+ case "real": t.kind = 15; break;
+ case "bool": t.kind = 16; break;
+ case "const": t.kind = 21; break;
+ case "unique": t.kind = 22; break;
+ case "extends": t.kind = 23; break;
+ case "complete": t.kind = 24; break;
+ case "function": t.kind = 25; break;
+ case "returns": t.kind = 26; break;
+ case "axiom": t.kind = 29; break;
+ case "type": t.kind = 30; break;
+ case "procedure": t.kind = 32; break;
+ case "implementation": t.kind = 33; break;
+ case "modifies": t.kind = 34; break;
+ case "free": t.kind = 35; break;
+ case "requires": t.kind = 36; break;
+ case "ensures": t.kind = 37; break;
+ case "goto": t.kind = 38; break;
+ case "return": t.kind = 39; break;
+ case "if": t.kind = 40; break;
+ case "else": t.kind = 41; break;
+ case "while": t.kind = 42; break;
+ case "invariant": t.kind = 43; break;
+ case "break": t.kind = 45; break;
+ case "assert": t.kind = 46; break;
+ case "assume": t.kind = 47; break;
+ case "havoc": t.kind = 48; break;
+ case "call": t.kind = 50; break;
+ case "forall": t.kind = 51; break;
+ case "div": t.kind = 73; break;
+ case "mod": t.kind = 74; break;
+ case "false": t.kind = 79; break;
+ case "true": t.kind = 80; break;
+ case "old": t.kind = 81; break;
+ case "then": t.kind = 84; break;
+ case "exists": t.kind = 86; break;
+ case "lambda": t.kind = 88; break;
default: break;
}
}
@@ -577,152 +579,181 @@ public class Scanner {
case 6:
if (ch == '"') {AddCh(); goto case 7;}
else if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 6;}
- else if (ch == 92) {AddCh(); goto case 10;}
+ else if (ch == 92) {AddCh(); goto case 17;}
else {goto case 0;}
case 7:
{t.kind = 4; break;}
case 8:
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;}
+ else if (ch == '-') {AddCh(); goto case 9;}
+ else {goto case 0;}
+ case 9:
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;}
+ else {goto case 0;}
+ case 10:
recEnd = pos; recKind = 5;
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 8;}
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;}
else {t.kind = 5; break;}
- case 9:
+ case 11:
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 12;}
+ else {goto case 0;}
+ case 12:
+ recEnd = pos; recKind = 6;
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 12;}
+ else if (ch == 'e') {AddCh(); goto case 13;}
+ else {t.kind = 6; break;}
+ case 13:
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 15;}
+ else if (ch == '-') {AddCh(); goto case 14;}
+ else {goto case 0;}
+ case 14:
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 15;}
+ else {goto case 0;}
+ case 15:
+ recEnd = pos; recKind = 6;
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 15;}
+ else {t.kind = 6; break;}
+ case 16:
recEnd = pos; recKind = 3;
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 9;}
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 16;}
else if (ch == 'b') {AddCh(); goto case 3;}
- else if (ch == '.') {AddCh(); goto case 8;}
+ else if (ch == 'e') {AddCh(); goto case 8;}
+ else if (ch == '.') {AddCh(); goto case 11;}
else {t.kind = 3; break;}
- case 10:
- if (ch == '"') {AddCh(); goto case 11;}
+ case 17:
+ if (ch == '"') {AddCh(); goto case 18;}
else if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 6;}
- else if (ch == 92) {AddCh(); goto case 10;}
+ else if (ch == 92) {AddCh(); goto case 17;}
else {goto case 0;}
- case 11:
+ case 18:
recEnd = pos; recKind = 4;
if (ch == '"') {AddCh(); goto case 7;}
else if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 6;}
- else if (ch == 92) {AddCh(); goto case 10;}
+ else if (ch == 92) {AddCh(); goto case 17;}
else {t.kind = 4; break;}
- case 12:
- {t.kind = 7; break;}
- case 13:
- {t.kind = 8; break;}
- case 14:
- {t.kind = 9; break;}
- case 15:
- {t.kind = 11; break;}
- case 16:
- {t.kind = 15; break;}
- case 17:
- {t.kind = 16; break;}
- case 18:
- {t.kind = 25; break;}
case 19:
- {t.kind = 42; break;}
+ {t.kind = 8; break;}
case 20:
- {t.kind = 47; break;}
+ {t.kind = 9; break;}
case 21:
- {t.kind = 50; break;}
+ {t.kind = 10; break;}
case 22:
- {t.kind = 51; break;}
+ {t.kind = 12; break;}
case 23:
- {t.kind = 52; break;}
+ {t.kind = 17; break;}
case 24:
- {t.kind = 53; break;}
+ {t.kind = 18; break;}
case 25:
- {t.kind = 55; break;}
+ {t.kind = 27; break;}
case 26:
- if (ch == '&') {AddCh(); goto case 27;}
- else {goto case 0;}
+ {t.kind = 49; break;}
case 27:
- {t.kind = 56; break;}
+ {t.kind = 52; break;}
case 28:
- {t.kind = 57; break;}
+ {t.kind = 53; break;}
case 29:
- {t.kind = 58; break;}
+ {t.kind = 54; break;}
case 30:
- {t.kind = 59; break;}
+ {t.kind = 55; break;}
case 31:
- {t.kind = 62; break;}
+ {t.kind = 57; break;}
case 32:
- {t.kind = 63; break;}
+ if (ch == '&') {AddCh(); goto case 33;}
+ else {goto case 0;}
case 33:
- {t.kind = 64; break;}
+ {t.kind = 58; break;}
case 34:
- {t.kind = 65; break;}
+ {t.kind = 59; break;}
case 35:
- {t.kind = 66; break;}
+ {t.kind = 60; break;}
case 36:
- {t.kind = 67; break;}
+ {t.kind = 61; break;}
case 37:
- {t.kind = 68; break;}
+ {t.kind = 64; break;}
case 38:
- {t.kind = 70; break;}
+ {t.kind = 65; break;}
case 39:
- {t.kind = 71; break;}
+ {t.kind = 66; break;}
case 40:
- {t.kind = 72; break;}
+ {t.kind = 67; break;}
case 41:
- {t.kind = 74; break;}
+ {t.kind = 68; break;}
case 42:
- {t.kind = 78; break;}
+ {t.kind = 69; break;}
case 43:
- {t.kind = 79; break;}
+ {t.kind = 70; break;}
case 44:
- {t.kind = 81; break;}
+ {t.kind = 72; break;}
case 45:
- {t.kind = 83; break;}
+ {t.kind = 75; break;}
case 46:
- {t.kind = 85; break;}
+ {t.kind = 76; break;}
case 47:
- {t.kind = 86; break;}
+ {t.kind = 78; break;}
case 48:
- {t.kind = 87; break;}
+ {t.kind = 82; break;}
case 49:
- recEnd = pos; recKind = 10;
- if (ch == '=') {AddCh(); goto case 20;}
- else if (ch == ':') {AddCh(); goto case 47;}
- else {t.kind = 10; break;}
+ {t.kind = 83; break;}
case 50:
- recEnd = pos; recKind = 17;
- if (ch == '=') {AddCh(); goto case 57;}
- else if (ch == ':') {AddCh(); goto case 33;}
- else {t.kind = 17; break;}
+ {t.kind = 85; break;}
case 51:
- recEnd = pos; recKind = 18;
- if (ch == '=') {AddCh(); goto case 31;}
- else {t.kind = 18; break;}
+ {t.kind = 87; break;}
case 52:
- recEnd = pos; recKind = 26;
- if (ch == '|') {AddCh(); goto case 43;}
- else {t.kind = 26; break;}
+ {t.kind = 89; break;}
case 53:
- recEnd = pos; recKind = 29;
- if (ch == '=') {AddCh(); goto case 58;}
- else {t.kind = 29; break;}
+ {t.kind = 90; break;}
case 54:
- if (ch == '|') {AddCh(); goto case 29;}
- else if (ch == '{') {AddCh(); goto case 42;}
- else {goto case 0;}
+ {t.kind = 91; break;}
case 55:
- recEnd = pos; recKind = 73;
- if (ch == '=') {AddCh(); goto case 32;}
- else {t.kind = 73; break;}
+ recEnd = pos; recKind = 11;
+ if (ch == '=') {AddCh(); goto case 26;}
+ else if (ch == ':') {AddCh(); goto case 53;}
+ else {t.kind = 11; break;}
case 56:
- recEnd = pos; recKind = 69;
- if (ch == '+') {AddCh(); goto case 37;}
- else {t.kind = 69; break;}
+ recEnd = pos; recKind = 19;
+ if (ch == '=') {AddCh(); goto case 64;}
+ else if (ch == ':') {AddCh(); goto case 39;}
+ else {t.kind = 19; break;}
case 57:
- recEnd = pos; recKind = 61;
- if (ch == '=') {AddCh(); goto case 59;}
- else {t.kind = 61; break;}
+ recEnd = pos; recKind = 20;
+ if (ch == '=') {AddCh(); goto case 37;}
+ else {t.kind = 20; break;}
case 58:
- recEnd = pos; recKind = 60;
- if (ch == '>') {AddCh(); goto case 23;}
- else {t.kind = 60; break;}
+ recEnd = pos; recKind = 28;
+ if (ch == '|') {AddCh(); goto case 49;}
+ else {t.kind = 28; break;}
case 59:
- recEnd = pos; recKind = 54;
- if (ch == '>') {AddCh(); goto case 21;}
- else {t.kind = 54; break;}
+ recEnd = pos; recKind = 31;
+ if (ch == '=') {AddCh(); goto case 65;}
+ else {t.kind = 31; break;}
+ case 60:
+ recEnd = pos; recKind = 44;
+ if (ch == '*') {AddCh(); goto case 46;}
+ else {t.kind = 44; break;}
+ case 61:
+ if (ch == '|') {AddCh(); goto case 35;}
+ else if (ch == '{') {AddCh(); goto case 48;}
+ else {goto case 0;}
+ case 62:
+ recEnd = pos; recKind = 77;
+ if (ch == '=') {AddCh(); goto case 38;}
+ else {t.kind = 77; break;}
+ case 63:
+ recEnd = pos; recKind = 71;
+ if (ch == '+') {AddCh(); goto case 43;}
+ else {t.kind = 71; break;}
+ case 64:
+ recEnd = pos; recKind = 63;
+ if (ch == '=') {AddCh(); goto case 66;}
+ else {t.kind = 63; break;}
+ case 65:
+ recEnd = pos; recKind = 62;
+ if (ch == '>') {AddCh(); goto case 29;}
+ else {t.kind = 62; break;}
+ case 66:
+ recEnd = pos; recKind = 56;
+ if (ch == '>') {AddCh(); goto case 27;}
+ else {t.kind = 56; break;}
}
t.val = new String(tval, 0, tlen);
diff --git a/Source/Core/StandardVisitor.cs b/Source/Core/StandardVisitor.cs
index 9bbeada1..66eee658 100644
--- a/Source/Core/StandardVisitor.cs
+++ b/Source/Core/StandardVisitor.cs
@@ -63,11 +63,6 @@ namespace Microsoft.Boogie {
Contract.Ensures(Contract.Result<Absy>() != null);
return node.StdDispatch(this);
}
- public virtual AIVariableExpr VisitAIVariableExpr(AIVariableExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AIVariableExpr>() != null);
- return node;
- }
public virtual Cmd VisitAssertCmd(AssertCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result<Cmd>() != null);
diff --git a/Source/Core/Util.cs b/Source/Core/Util.cs
index a8e12f63..9a7fec0c 100644
--- a/Source/Core/Util.cs
+++ b/Source/Core/Util.cs
@@ -451,7 +451,7 @@ namespace Microsoft.Boogie {
op = " && ";
break;
case Microsoft.Boogie.BinaryOperator.Opcode.Div:
- op = " / ";
+ op = " div ";
break;
case Microsoft.Boogie.BinaryOperator.Opcode.Eq:
op = " == ";
@@ -475,7 +475,7 @@ namespace Microsoft.Boogie {
op = " < ";
break;
case Microsoft.Boogie.BinaryOperator.Opcode.Mod:
- op = " % ";
+ op = " mod ";
break;
case Microsoft.Boogie.BinaryOperator.Opcode.Mul:
op = " * ";
@@ -486,6 +486,12 @@ namespace Microsoft.Boogie {
case Microsoft.Boogie.BinaryOperator.Opcode.Or:
op = " || ";
break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Pow:
+ op = " ** ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.RealDiv:
+ op = " / ";
+ break;
case Microsoft.Boogie.BinaryOperator.Opcode.Sub:
op = " - ";
break;
diff --git a/Source/Dafny/Cloner.cs b/Source/Dafny/Cloner.cs
index 095534e6..38c793c5 100644
--- a/Source/Dafny/Cloner.cs
+++ b/Source/Dafny/Cloner.cs
@@ -444,6 +444,10 @@ namespace Microsoft.Dafny
var s = (ParallelStmt)stmt;
r = new ParallelStmt(Tok(s.Tok), s.BoundVars.ConvertAll(CloneBoundVar), null, CloneExpr(s.Range), s.Ens.ConvertAll(CloneMayBeFreeExpr), CloneStmt(s.Body));
+ } else if (stmt is CalcStmt) {
+ var s = (CalcStmt)stmt;
+ r = new CalcStmt(Tok(s.Tok), s.Op, s.Lines.ConvertAll(CloneExpr), s.Hints.ConvertAll(CloneBlockStmt), new List<Nullable<BinaryExpr.Opcode>>(s.CustomOps));
+
} else if (stmt is MatchStmt) {
var s = (MatchStmt)stmt;
r = new MatchStmt(Tok(s.Tok), CloneExpr(s.Source),
diff --git a/Source/Dafny/Dafny.atg b/Source/Dafny/Dafny.atg
index bc972495..4c425497 100644
--- a/Source/Dafny/Dafny.atg
+++ b/Source/Dafny/Dafny.atg
@@ -863,6 +863,7 @@ OneStmt<out Statement/*!*/ s>
| WhileStmt<out s>
| MatchStmt<out s>
| ParallelStmt<out s>
+ | CalcStmt<out s>
| "label" (. x = t; .)
NoUSIdent<out id> ":"
OneStmt<out s> (. s.Labels = new LList<Label>(new Label(x, id.val), s.Labels); .)
@@ -1315,6 +1316,82 @@ ParallelStmt<out Statement/*!*/ s>
BlockStmt<out block, out bodyStart, out bodyEnd>
(. s = new ParallelStmt(x, bvars, attrs, range, ens, block); .)
.
+
+CalcStmt<out Statement/*!*/ s>
+= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null);
+ Token x;
+ BinaryExpr.Opcode op, calcOp = BinaryExpr.Opcode.Eq, resOp = BinaryExpr.Opcode.Eq;
+ var lines = new List<Expression/*!*/>();
+ var hints = new List<BlockStmt/*!*/>();
+ var customOps = new List<BinaryExpr.Opcode?>();
+ BinaryExpr.Opcode? maybeOp;
+ Expression/*!*/ e;
+ BlockStmt/*!*/ h;
+ IToken opTok;
+ .)
+ "calc" (. x = t; .)
+ [ CalcOp<out opTok, out calcOp> (. maybeOp = Microsoft.Dafny.CalcStmt.ResultOp(calcOp, calcOp); // guard against non-trasitive calcOp (like !=)
+ if (maybeOp == null) {
+ SemErr(opTok, "the main operator of a calculation must be transitive");
+ }
+ resOp = calcOp;
+ .)
+ ]
+ "{"
+ [ Expression<out e> (. lines.Add(e); .)
+ ";"
+ {
+ Hint<out h> (. hints.Add(h); .)
+ ( CalcOp<out opTok, out op> (. maybeOp = Microsoft.Dafny.CalcStmt.ResultOp(resOp, op);
+ if (maybeOp == null) {
+ customOps.Add(null); // pretend the operator was not there to satisfy the precondition of the CalcStmt contructor
+ SemErr(opTok, "this operator cannot continue this calculation");
+ } else {
+ customOps.Add(op);
+ resOp = (BinaryExpr.Opcode)maybeOp;
+ }
+ .)
+ | (. customOps.Add(null); .)
+ )
+ Expression<out e> (. lines.Add(e); .)
+ ";"
+ }
+ ]
+ "}"
+ (. s = new CalcStmt(x, calcOp, lines, hints, customOps); .)
+ .
+CalcOp<out IToken x, out BinaryExpr.Opcode/*!*/ op>
+= (. Contract.Ensures(Microsoft.Dafny.CalcStmt.ValidOp(Contract.ValueAtReturn(out op)));
+ op = BinaryExpr.Opcode.Eq; // Returns Eq if parsing fails because it is compatible with any other operator
+ x = null;
+ .)
+ ( "==" (. x = t; op = BinaryExpr.Opcode.Eq; .)
+ | "<" (. x = t; op = BinaryExpr.Opcode.Lt; .)
+ | ">" (. x = t; op = BinaryExpr.Opcode.Gt; .)
+ | "<=" (. x = t; op = BinaryExpr.Opcode.Le; .)
+ | ">=" (. x = t; op = BinaryExpr.Opcode.Ge; .)
+ | "!=" (. x = t; op = BinaryExpr.Opcode.Neq; .)
+ | '\u2260' (. x = t; op = BinaryExpr.Opcode.Neq; .)
+ | '\u2264' (. x = t; op = BinaryExpr.Opcode.Le; .)
+ | '\u2265' (. x = t; op = BinaryExpr.Opcode.Ge; .)
+ | EquivOp (. x = t; op = BinaryExpr.Opcode.Iff; .)
+ | ImpliesOp (. x = t; op = BinaryExpr.Opcode.Imp; .)
+ )
+ .
+Hint<out BlockStmt s>
+= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); // returns an empty block statement if the hint is empty
+ var subhints = new List<Statement/*!*/>();
+ IToken bodyStart, bodyEnd;
+ BlockStmt/*!*/ block;
+ Statement/*!*/ calc;
+ Token x = la;
+ .)
+ { BlockStmt<out block, out bodyStart, out bodyEnd> (. subhints.Add(block); .)
+ | CalcStmt<out calc> (. subhints.Add(calc); .)
+ }
+ (. s = new BlockStmt(x, subhints); // if the hint is empty x is the first token of the next line, but it doesn't matter cause the block statement is just used as a container
+ .)
+ .
/*------------------------------------------------------------------------*/
Expression<out Expression/*!*/ e>
=
@@ -1600,7 +1677,7 @@ MapDisplayExpr<IToken/*!*/ mapToken, out Expression e>
.
MapLiteralExpressions<.out List<ExpressionPair> elements.>
= (. Expression/*!*/ d, r;
- elements = new List<ExpressionPair/*!*/>(); .)
+ elements = new List<ExpressionPair/*!*/>(); .)
Expression<out d> ":=" Expression<out r> (. elements.Add(new ExpressionPair(d,r)); .)
{ "," Expression<out d> ":=" Expression<out r>(. elements.Add(new ExpressionPair(d,r)); .)
}
diff --git a/Source/Dafny/DafnyAst.cs b/Source/Dafny/DafnyAst.cs
index ccf96486..345fc6fa 100644
--- a/Source/Dafny/DafnyAst.cs
+++ b/Source/Dafny/DafnyAst.cs
@@ -2801,6 +2801,113 @@ namespace Microsoft.Dafny {
}
}
+ public class CalcStmt : Statement
+ {
+ public readonly BinaryExpr.Opcode/*!*/ Op; // main operator of the calculation
+ public readonly List<Expression/*!*/> Lines;
+ public readonly List<BlockStmt/*!*/> Hints; // Hints[i] comes after line i; block statement is used as a container for multiple sub-hints
+ public readonly List<BinaryExpr.Opcode?> CustomOps; // CustomOps[i] comes after line i; null denotes the absence of a custom operator
+ public readonly List<BinaryExpr/*!*/> Steps; // expressions li op l<i + 1>, filled in during resolution in order to get the correct op
+ public BinaryExpr Result; // expression l0 op ln, filled in during resolution in order to get the correct op
+
+ public static readonly BinaryExpr.Opcode/*!*/ DefaultOp = BinaryExpr.Opcode.Eq;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(ValidOp(Op));
+ Contract.Invariant(Lines != null);
+ Contract.Invariant(Hints != null);
+ Contract.Invariant(CustomOps != null);
+ Contract.Invariant(Steps != null);
+ Contract.Invariant(Hints.Count == Math.Max(Lines.Count - 1, 0));
+ Contract.Invariant(CustomOps.Count == Hints.Count);
+ }
+
+ public CalcStmt(IToken tok, BinaryExpr.Opcode/*!*/ op, List<Expression/*!*/> lines, List<BlockStmt/*!*/> hints, List<BinaryExpr.Opcode?> customOps)
+ : base(tok)
+ {
+ Contract.Requires(tok != null);
+ Contract.Requires(ValidOp(op));
+ Contract.Requires(lines != null);
+ Contract.Requires(hints != null);
+ Contract.Requires(customOps != null);
+ Contract.Requires(cce.NonNullElements(lines));
+ Contract.Requires(cce.NonNullElements(hints));
+ Contract.Requires(hints.Count == Math.Max(lines.Count - 1, 0));
+ Contract.Requires(customOps.Count == hints.Count);
+ this.Op = op;
+ this.Lines = lines;
+ this.Hints = hints;
+ this.CustomOps = customOps;
+ this.Steps = new List<BinaryExpr>();
+ this.Result = null;
+ }
+
+ public override IEnumerable<Statement> SubStatements
+ {
+ get {
+ foreach (var h in Hints) {
+ yield return h;
+ }
+ }
+ }
+ public override IEnumerable<Expression> SubExpressions
+ {
+ get {
+ foreach (var l in Lines) {
+ yield return l;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Is op a valid calculation operator (i.e. a transitive relational operator)?
+ /// </summary>
+ [Pure]
+ public static bool ValidOp(BinaryExpr.Opcode op) {
+ return op == BinaryExpr.Opcode.Eq || op == BinaryExpr.Opcode.Lt || op == BinaryExpr.Opcode.Le || op == BinaryExpr.Opcode.Gt || op == BinaryExpr.Opcode.Ge
+ || op == BinaryExpr.Opcode.Neq
+ || op == BinaryExpr.Opcode.Iff || op == BinaryExpr.Opcode.Imp;
+ }
+
+ /// <summary>
+ /// Does op1 subsume op2 (i.e. forall x, y, z :: (x op1 y op2 z) || (x op2 y op1 z) ==> x op1 z)?
+ /// </summary>
+ [Pure]
+ private static bool Subsumes(BinaryExpr.Opcode op1, BinaryExpr.Opcode op2) {
+ Contract.Requires(ValidOp(op1) && ValidOp(op2));
+ if (op1 == BinaryExpr.Opcode.Neq || op2 == BinaryExpr.Opcode.Neq)
+ return op2 == BinaryExpr.Opcode.Eq;
+ if (op1 == op2)
+ return true;
+ if (op1 == BinaryExpr.Opcode.Iff || op1 == BinaryExpr.Opcode.Imp || op2 == BinaryExpr.Opcode.Iff || op2 == BinaryExpr.Opcode.Imp)
+ return op2 == BinaryExpr.Opcode.Eq ||
+ (op1 == BinaryExpr.Opcode.Imp && op2 == BinaryExpr.Opcode.Iff) ||
+ (op1 == BinaryExpr.Opcode.Eq && op2 == BinaryExpr.Opcode.Iff);
+ return op2 == BinaryExpr.Opcode.Eq ||
+ (op1 == BinaryExpr.Opcode.Lt && op2 == BinaryExpr.Opcode.Le) ||
+ (op1 == BinaryExpr.Opcode.Gt && op2 == BinaryExpr.Opcode.Ge);
+ }
+
+ /// <summary>
+ /// Resulting operator x op z if x op1 y op2 z.
+ /// (Least upper bound in the Subsumes order).
+ /// Returns null if neither of op1 or op2 subsumes the other.
+ /// </summary>
+ [Pure]
+ public static BinaryExpr.Opcode? ResultOp(BinaryExpr.Opcode op1, BinaryExpr.Opcode op2) {
+ Contract.Requires(ValidOp(op1) && ValidOp(op2));
+ Contract.Ensures(Contract.Result<BinaryExpr.Opcode?>() == null || ValidOp((BinaryExpr.Opcode)Contract.Result<BinaryExpr.Opcode?>()));
+ if (Subsumes(op1, op2)) {
+ return op1;
+ } else if (Subsumes(op2, op1)) {
+ return op2;
+ }
+ return null;
+ }
+ }
+
public class MatchStmt : Statement
{
[ContractInvariantMethod]
diff --git a/Source/Dafny/DafnyPipeline.csproj b/Source/Dafny/DafnyPipeline.csproj
index f572f419..b4c2ae1e 100644
--- a/Source/Dafny/DafnyPipeline.csproj
+++ b/Source/Dafny/DafnyPipeline.csproj
@@ -127,10 +127,6 @@
<CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
</PropertyGroup>
<ItemGroup>
- <Reference Include="AIFramework, Version=2.0.0.0, Culture=neutral, PublicKeyToken=736440c9b414ea16, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\Binaries\AIFramework.dll</HintPath>
- </Reference>
<Reference Include="Basetypes, Version=2.0.0.0, Culture=neutral, PublicKeyToken=736440c9b414ea16, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Binaries\Basetypes.dll</HintPath>
diff --git a/Source/Dafny/Printer.cs b/Source/Dafny/Printer.cs
index fe602f86..36658e2f 100644
--- a/Source/Dafny/Printer.cs
+++ b/Source/Dafny/Printer.cs
@@ -8,6 +8,7 @@ using System.IO;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Numerics;
+using System.Linq;
using Bpl = Microsoft.Boogie;
namespace Microsoft.Dafny {
@@ -620,6 +621,40 @@ namespace Microsoft.Dafny {
}
PrintStatement(s.Body, indent);
+ } else if (stmt is CalcStmt) {
+ CalcStmt s = (CalcStmt)stmt;
+ wr.Write("calc ");
+ if (s.Op != CalcStmt.DefaultOp) {
+ wr.Write(BinaryExpr.OpcodeString(s.Op));
+ wr.Write(" ");
+ }
+ wr.WriteLine("{");
+ int lineInd = indent + IndentAmount;
+ if (s.Lines.Count > 0) {
+ Indent(lineInd);
+ PrintExpression(s.Lines.First(), lineInd);
+ wr.WriteLine(";");
+ }
+ for (var i = 1; i < s.Lines.Count; i++){
+ var e = s.Lines[i];
+ var h = s.Hints[i - 1];
+ var op = s.CustomOps[i - 1];
+ foreach (var st in h.Body) {
+ Indent(lineInd);
+ PrintStatement(st, lineInd);
+ wr.WriteLine();
+ }
+ Indent(lineInd);
+ if (op != null && (BinaryExpr.Opcode)op != s.Op) {
+ wr.Write(BinaryExpr.OpcodeString((BinaryExpr.Opcode)op));
+ wr.Write(" ");
+ }
+ PrintExpression(e, lineInd);
+ wr.WriteLine(";");
+ }
+ Indent(indent);
+ wr.Write("}");
+
} else if (stmt is MatchStmt) {
MatchStmt s = (MatchStmt)stmt;
wr.Write("match ");
diff --git a/Source/Dafny/Resolver.cs b/Source/Dafny/Resolver.cs
index ae43dae4..61c5800f 100644
--- a/Source/Dafny/Resolver.cs
+++ b/Source/Dafny/Resolver.cs
@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Diagnostics.Contracts;
+using System.Linq;
using Microsoft.Boogie;
namespace Microsoft.Dafny
@@ -1886,6 +1887,11 @@ namespace Microsoft.Dafny
var s = (ParallelStmt)stmt;
CheckTypeInference(s.Range);
CheckTypeInference(s.Body);
+ } else if (stmt is CalcStmt) {
+ // NadiaToDo: is this correct?
+ var s = (CalcStmt)stmt;
+ s.SubExpressions.Iter(e => CheckTypeInference(e));
+ s.SubStatements.Iter(CheckTypeInference);
} else if (stmt is MatchStmt) {
var s = (MatchStmt)stmt;
CheckTypeInference(s.Source);
@@ -3546,6 +3552,48 @@ namespace Microsoft.Dafny
}
CheckParallelBodyRestrictions(s.Body, s.Kind);
}
+
+ } else if (stmt is CalcStmt) {
+ var prevErrorCount = ErrorCount;
+ CalcStmt s = (CalcStmt)stmt;
+ s.IsGhost = true;
+ if (s.Lines.Count > 0) {
+ var resOp = s.Op;
+ var e0 = s.Lines.First();
+ ResolveExpression(e0, true);
+ Contract.Assert(e0.Type != null); // follows from postcondition of ResolveExpression
+ for (int i = 1; i < s.Lines.Count; i++) {
+ var e1 = s.Lines[i];
+ ResolveExpression(e1, true);
+ Contract.Assert(e1.Type != null); // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(e0.Type, e1.Type)) {
+ Error(e1, "all lines in a calculation must have the same type (got {0} after {1})", e1.Type, e0.Type);
+ } else {
+ BinaryExpr step;
+ var op = s.CustomOps[i - 1];
+ if (op == null) {
+ step = new BinaryExpr(e0.tok, s.Op, e0, e1); // Use calc-wide operator
+ } else {
+ step = new BinaryExpr(e0.tok, (BinaryExpr.Opcode)op, e0, e1); // Use custom line operator
+ Contract.Assert(CalcStmt.ResultOp(resOp, (BinaryExpr.Opcode)op) != null); // This was checked during parsing
+ resOp = (BinaryExpr.Opcode)CalcStmt.ResultOp(resOp, (BinaryExpr.Opcode)op);
+ }
+ ResolveExpression(step, true);
+ s.Steps.Add(step);
+ }
+ e0 = e1;
+ }
+ foreach (var h in s.Hints) {
+ ResolveStatement(h, true, method);
+ }
+ if (prevErrorCount == ErrorCount && s.Steps.Count > 0) {
+ // do not build Result if there were errors, as it might be ill-typed and produce unnecessary resolution errors
+ s.Result = new BinaryExpr(s.Tok, resOp, s.Lines.First(), s.Lines.Last());
+ ResolveExpression(s.Result, true);
+ }
+ }
+ Contract.Assert(prevErrorCount != ErrorCount || s.Steps.Count == s.Hints.Count);
+ Contract.Assert(prevErrorCount != ErrorCount || s.Steps.Count == 0 || s.Result != null);
} else if (stmt is MatchStmt) {
MatchStmt s = (MatchStmt)stmt;
@@ -4147,6 +4195,10 @@ namespace Microsoft.Dafny
Contract.Assert(false); // unexpected kind
break;
}
+
+ } else if (stmt is CalcStmt) {
+ // cool
+ // NadiaTodo: ...I assume because it's always ghost
} else if (stmt is MatchStmt) {
var s = (MatchStmt)stmt;
diff --git a/Source/Dafny/Translator.cs b/Source/Dafny/Translator.cs
index 5d3d359a..40795129 100644
--- a/Source/Dafny/Translator.cs
+++ b/Source/Dafny/Translator.cs
@@ -4384,6 +4384,61 @@ namespace Microsoft.Dafny {
Contract.Assert(false); // unexpected kind
}
+ } else if (stmt is CalcStmt) {
+ /* Translate into:
+ if (*) {
+ // line well-formedness checks;
+ } else if (*) {
+ hint0;
+ assert t0 op t1;
+ assume false;
+ } else if (*) { ...
+ } else if (*) {
+ hint<n-1>;
+ assert t<n-1> op tn;
+ assume false;
+ }
+ assume t0 op tn;
+ */
+ var s = (CalcStmt)stmt;
+ Contract.Assert(s.Steps.Count == s.Hints.Count); // established by the resolver
+ AddComment(builder, stmt, "calc statement");
+ if (s.Lines.Count > 0) {
+ Bpl.IfCmd ifCmd = null;
+ Bpl.StmtListBuilder b;
+ // check steps:
+ for (int i = s.Steps.Count; 0 <= --i; ) {
+ b = new Bpl.StmtListBuilder();
+ TrStmt(s.Hints[i], b, locals, etran);
+ bool splitHappened;
+ var ss = TrSplitExpr(s.Steps[i], etran, out splitHappened);
+ if (!splitHappened) {
+ b.Add(AssertNS(s.Lines[i + 1].tok, etran.TrExpr(s.Steps[i]), "the calculation step between the previous line and this line might not hold"));
+ } else {
+ foreach (var split in ss) {
+ if (!split.IsFree) {
+ b.Add(AssertNS(s.Lines[i + 1].tok, split.E, "the calculation step between the previous line and this line might not hold"));
+ }
+ }
+ }
+ b.Add(new Bpl.AssumeCmd(s.Tok, Bpl.Expr.False));
+ ifCmd = new Bpl.IfCmd(s.Tok, null, b.Collect(s.Tok), ifCmd, null);
+ }
+ // check well-formedness of lines:
+ b = new Bpl.StmtListBuilder();
+ foreach (var e in s.Lines) {
+ TrStmt_CheckWellformed(e, b, locals, etran, false);
+ }
+ b.Add(new Bpl.AssumeCmd(s.Tok, Bpl.Expr.False));
+ ifCmd = new Bpl.IfCmd(s.Tok, null, b.Collect(s.Tok), ifCmd, null);
+ builder.Add(ifCmd);
+ // assume result:
+ if (s.Steps.Count > 0) {
+ Contract.Assert(s.Result != null); // established by the resolver
+ builder.Add(new Bpl.AssumeCmd(s.Tok, etran.TrExpr(s.Result)));
+ }
+ }
+
} else if (stmt is MatchStmt) {
var s = (MatchStmt)stmt;
TrStmt_CheckWellformed(s.Source, builder, locals, etran, true);
diff --git a/Source/DafnyDriver/DafnyDriver.cs b/Source/DafnyDriver/DafnyDriver.cs
index 64f5fbbb..80f78d16 100644
--- a/Source/DafnyDriver/DafnyDriver.cs
+++ b/Source/DafnyDriver/DafnyDriver.cs
@@ -22,7 +22,6 @@ namespace Microsoft.Dafny
using System.Diagnostics;
using VC;
using System.CodeDom.Compiler;
- using AI = Microsoft.AbstractInterpretationFramework;
public class DafnyDriver
{
@@ -536,9 +535,6 @@ namespace Microsoft.Dafny
if (CommandLineOptions.Clo.UseAbstractInterpretation) {
if (CommandLineOptions.Clo.Ai.J_Intervals || CommandLineOptions.Clo.Ai.J_Trivial) {
Microsoft.Boogie.AbstractInterpretation.NativeAbstractInterpretation.RunAbstractInterpretation(program);
- } else if (CommandLineOptions.Clo.Ai.AnySet) {
- // run one of the old domains
- Microsoft.Boogie.AbstractInterpretation.AbstractInterpretation.RunAbstractInterpretation(program);
} else {
// use /infer:j as the default
CommandLineOptions.Clo.Ai.J_Intervals = true;
@@ -575,13 +571,7 @@ namespace Microsoft.Dafny
ConditionGeneration vcgen = null;
try
{
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed)
- {
- vcgen = new DCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend);
- } else
- {
- vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend);
- }
+ vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend);
}
catch (ProverException e)
{
diff --git a/Source/DafnyDriver/DafnyDriver.csproj b/Source/DafnyDriver/DafnyDriver.csproj
index 5dac8f59..6f32302d 100644
--- a/Source/DafnyDriver/DafnyDriver.csproj
+++ b/Source/DafnyDriver/DafnyDriver.csproj
@@ -127,9 +127,6 @@
<Reference Include="AbsInt">
<HintPath>..\..\Binaries\AbsInt.dll</HintPath>
</Reference>
- <Reference Include="AIFramework">
- <HintPath>..\..\Binaries\AIFramework.dll</HintPath>
- </Reference>
<Reference Include="Core">
<HintPath>..\..\Binaries\Core.dll</HintPath>
</Reference>
diff --git a/Source/VCGeneration/DoomCheck.cs b/Source/Doomed/DoomCheck.cs
index 8571caee..1cbbeabf 100644
--- a/Source/VCGeneration/DoomCheck.cs
+++ b/Source/Doomed/DoomCheck.cs
@@ -11,8 +11,7 @@ using System.Diagnostics;
using System.Threading;
using System.IO;
using Microsoft.Boogie;
-using Graphing;
-using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Boogie.GraphUtil;
using System.Diagnostics.Contracts;
using Microsoft.Basetypes;
using Microsoft.Boogie.VCExprAST;
diff --git a/Source/VCGeneration/DoomErrorHandler.cs b/Source/Doomed/DoomErrorHandler.cs
index b0821240..33d8b68e 100644
--- a/Source/VCGeneration/DoomErrorHandler.cs
+++ b/Source/Doomed/DoomErrorHandler.cs
@@ -5,8 +5,7 @@ using System.Diagnostics;
using System.Threading;
using System.IO;
using Microsoft.Boogie;
-using Graphing;
-using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Boogie.GraphUtil;
using System.Diagnostics.Contracts;
using Microsoft.Basetypes;
using Microsoft.Boogie.VCExprAST;
diff --git a/Source/Doomed/Doomed.csproj b/Source/Doomed/Doomed.csproj
new file mode 100644
index 00000000..c3319022
--- /dev/null
+++ b/Source/Doomed/Doomed.csproj
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{884386A3-58E9-40BB-A273-B24976775553}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Doomed</RootNamespace>
+ <AssemblyName>Doomed</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="DoomCheck.cs" />
+ <Compile Include="DoomedLoopUnrolling.cs" />
+ <Compile Include="DoomedStrategy.cs" />
+ <Compile Include="DoomErrorHandler.cs" />
+ <Compile Include="HasseDiagram.cs" />
+ <Compile Include="VCDoomed.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43dfad18-3e35-4558-9be2-caff6b5ba8a0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{accc0156-0921-43ed-8f67-ad8bdc8cde31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{b230a69c-c466-4065-b9c1-84d80e76d802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Graph\Graph.csproj">
+ <Project>{69a2b0b8-bcac-4101-ae7a-556fcc58c06e}</Project>
+ <Name>Graph</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Model\Model.csproj">
+ <Project>{acef88d5-dadd-46da-bae1-2144d63f4c83}</Project>
+ <Name>Model</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{fcd3ac7f-9dfd-46c8-ab1e-09f0b0f16dc5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\VCExpr\VCExpr.csproj">
+ <Project>{56ffdbca-7d14-43b8-a6ca-22a20e417ee1}</Project>
+ <Name>VCExpr</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
+ <Project>{e1f10180-c7b9-4147-b51f-fa1b701966dc}</Project>
+ <Name>VCGeneration</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Source/VCGeneration/DoomedLoopUnrolling.cs b/Source/Doomed/DoomedLoopUnrolling.cs
index 9d58d227..e65a570a 100644
--- a/Source/VCGeneration/DoomedLoopUnrolling.cs
+++ b/Source/Doomed/DoomedLoopUnrolling.cs
@@ -5,8 +5,7 @@ using System.Diagnostics;
using System.Threading;
using System.IO;
using Microsoft.Boogie;
-using Graphing;
-using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Boogie.GraphUtil;
using System.Diagnostics.Contracts;
using Microsoft.Basetypes;
using Microsoft.Boogie.VCExprAST;
diff --git a/Source/VCGeneration/DoomedStrategy.cs b/Source/Doomed/DoomedStrategy.cs
index 18de31c7..eb5716bb 100644
--- a/Source/VCGeneration/DoomedStrategy.cs
+++ b/Source/Doomed/DoomedStrategy.cs
@@ -10,8 +10,7 @@ using System.Diagnostics;
using System.Threading;
using System.IO;
using Microsoft.Boogie;
-using Graphing;
-using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Boogie.GraphUtil;
using System.Diagnostics.Contracts;
using Microsoft.Basetypes;
using Microsoft.Boogie.VCExprAST;
diff --git a/Source/VCGeneration/HasseDiagram.cs b/Source/Doomed/HasseDiagram.cs
index db777336..b2ece2df 100644
--- a/Source/VCGeneration/HasseDiagram.cs
+++ b/Source/Doomed/HasseDiagram.cs
@@ -10,8 +10,7 @@ using System.Diagnostics;
using System.Threading;
using System.IO;
using Microsoft.Boogie;
-using Graphing;
-using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Boogie.GraphUtil;
using System.Diagnostics.Contracts;
using Microsoft.Basetypes;
using Microsoft.Boogie.VCExprAST;
diff --git a/Source/VCGeneration/VCDoomed.cs b/Source/Doomed/VCDoomed.cs
index 15c6e2aa..fadb2ea7 100644
--- a/Source/VCGeneration/VCDoomed.cs
+++ b/Source/Doomed/VCDoomed.cs
@@ -10,8 +10,7 @@ using System.Diagnostics;
using System.Threading;
using System.IO;
using Microsoft.Boogie;
-using Graphing;
-using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Boogie.GraphUtil;
using System.Diagnostics.Contracts;
using Microsoft.Basetypes;
using Microsoft.Boogie.VCExprAST;
diff --git a/Source/GPUVerify.sln b/Source/GPUVerify.sln
index 7853459f..75354021 100644
--- a/Source/GPUVerify.sln
+++ b/Source/GPUVerify.sln
@@ -27,8 +27,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "Model\Model.csproj
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VCExpr", "VCExpr\VCExpr.csproj", "{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Isabelle", "Provers\Isabelle\Isabelle.csproj", "{435D5BD0-6F62-49F8-BB24-33E2257519AD}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GPUVerifyBoogieDriver", "GPUVerifyBoogieDriver\GPUVerifyBoogieDriver.csproj", "{FD2A2C67-1BD6-4A1A-B65B-B057267E24A3}"
EndProject
Global
@@ -309,26 +307,6 @@ Global
{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Mixed Platforms.ActiveCfg = z3apidebug|Any CPU
{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Mixed Platforms.Build.0 = z3apidebug|Any CPU
{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|x86.ActiveCfg = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|x86.ActiveCfg = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Any CPU.Build.0 = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|x86.ActiveCfg = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Mixed Platforms.ActiveCfg = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Mixed Platforms.Build.0 = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
{FD2A2C67-1BD6-4A1A-B65B-B057267E24A3}.Checked|Any CPU.ActiveCfg = Release|x86
{FD2A2C67-1BD6-4A1A-B65B-B057267E24A3}.Checked|Mixed Platforms.ActiveCfg = Release|x86
{FD2A2C67-1BD6-4A1A-B65B-B057267E24A3}.Checked|Mixed Platforms.Build.0 = Release|x86
diff --git a/Source/GPUVerify/ArrayControlFlowAnalyser.cs b/Source/GPUVerify/ArrayControlFlowAnalyser.cs
index d7841f0e..8e52b9ef 100644
--- a/Source/GPUVerify/ArrayControlFlowAnalyser.cs
+++ b/Source/GPUVerify/ArrayControlFlowAnalyser.cs
@@ -172,8 +172,12 @@ namespace GPUVerify
{
CallCmd callCmd = c as CallCmd;
- if (callCmd.callee != verifier.BarrierProcedure.Name)
- {
+ if (QKeyValue.FindBoolAttribute(callCmd.Proc.Attributes, "barrier_invariant") ||
+ QKeyValue.FindBoolAttribute(callCmd.Proc.Attributes, "binary_barrier_invariant")) {
+ foreach (Expr param in callCmd.Ins) {
+ ExprMayAffectControlFlow(impl, param);
+ }
+ } else if(callCmd.callee != verifier.BarrierProcedure.Name) {
Implementation CalleeImplementation = verifier.GetImplementation(callCmd.callee);
for (int i = 0; i < CalleeImplementation.InParams.Length; i++)
@@ -218,6 +222,10 @@ namespace GPUVerify
var assumeCmd = c as AssumeCmd;
ExprMayAffectControlFlow(impl, assumeCmd.Expr);
}
+ else if (c is AssertCmd) {
+ var assertCmd = c as AssertCmd;
+ ExprMayAffectControlFlow(impl, assertCmd.Expr);
+ }
}
}
diff --git a/Source/GPUVerify/BarrierInvariantDescriptor.cs b/Source/GPUVerify/BarrierInvariantDescriptor.cs
new file mode 100644
index 00000000..2b7450c9
--- /dev/null
+++ b/Source/GPUVerify/BarrierInvariantDescriptor.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics;
+using Microsoft.Boogie;
+
+namespace GPUVerify {
+ abstract class BarrierInvariantDescriptor {
+
+ protected Expr Predicate;
+ protected Expr BarrierInvariant;
+ protected QKeyValue SourceLocationInfo;
+ protected KernelDualiser Dualiser;
+ protected string ProcName;
+
+ public BarrierInvariantDescriptor(Expr Predicate, Expr BarrierInvariant,
+ QKeyValue SourceLocationInfo,
+ KernelDualiser Dualiser, string ProcName) {
+ this.Predicate = Predicate;
+ this.BarrierInvariant = BarrierInvariant;
+ this.SourceLocationInfo = SourceLocationInfo;
+ this.Dualiser = Dualiser;
+ this.ProcName = ProcName;
+ }
+
+ internal abstract AssertCmd GetAssertCmd();
+
+ internal abstract List<AssumeCmd> GetInstantiationCmds();
+
+ protected Expr NonNegative(Expr e) {
+ return Dualiser.verifier.MakeBVSge(
+ e, GPUVerifier.ZeroBV());
+ }
+
+ protected Expr NotTooLarge(Expr e) {
+ return Dualiser.verifier.MakeBVSlt(e,
+ new IdentifierExpr(Token.NoToken,
+ Dualiser.verifier.GetGroupSize("X")));
+ }
+
+ }
+}
diff --git a/Source/GPUVerify/BinaryBarrierInvariantDescriptor.cs b/Source/GPUVerify/BinaryBarrierInvariantDescriptor.cs
new file mode 100644
index 00000000..8be05ecb
--- /dev/null
+++ b/Source/GPUVerify/BinaryBarrierInvariantDescriptor.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+
+namespace GPUVerify {
+ class BinaryBarrierInvariantDescriptor : BarrierInvariantDescriptor {
+
+ private List<Tuple<Expr, Expr>> InstantiationExprPairs;
+
+ public BinaryBarrierInvariantDescriptor(Expr Predicate, Expr BarrierInvariant,
+ QKeyValue SourceLocationInfo,
+ KernelDualiser Dualiser, string ProcName) :
+ base(Predicate, BarrierInvariant, SourceLocationInfo, Dualiser, ProcName) {
+ InstantiationExprPairs = new List<Tuple<Expr, Expr>>();
+ }
+
+ public void AddInstantiationExprPair(Expr first, Expr second) {
+ InstantiationExprPairs.Add(new Tuple<Expr, Expr>(first, second));
+ }
+
+ internal override AssertCmd GetAssertCmd() {
+ var vd = new VariableDualiser(1, Dualiser.verifier.uniformityAnalyser, ProcName);
+ return new AssertCmd(
+ Token.NoToken,
+ Expr.Imp(GPUVerifier.ThreadsInSameGroup(),
+ vd.VisitExpr(Expr.Imp(Predicate, BarrierInvariant))),
+ Dualiser.MakeThreadSpecificAttributes(SourceLocationInfo, 1));
+ }
+
+ internal override List<AssumeCmd> GetInstantiationCmds() {
+ var result = new List<AssumeCmd>();
+ foreach (var Instantiation in InstantiationExprPairs) {
+ foreach (var Thread in new int[] { 1, 2 }) {
+
+ var vd = new VariableDualiser(Thread, Dualiser.verifier.uniformityAnalyser, ProcName);
+
+ var ThreadInstantiationExpr = vd.VisitExpr(Instantiation.Item1);
+ var OtherThreadInstantiationExpr = vd.VisitExpr(Instantiation.Item2);
+
+ var ti = new ThreadPairInstantiator(Dualiser.verifier, ThreadInstantiationExpr, OtherThreadInstantiationExpr, Thread);
+
+ result.Add(new AssumeCmd(
+ Token.NoToken,
+ Expr.Imp(vd.VisitExpr(Predicate),
+ Expr.Imp(
+ Expr.And(
+ Expr.And(
+ Expr.And(NonNegative(ThreadInstantiationExpr),
+ NotTooLarge(ThreadInstantiationExpr)),
+ Expr.And(NonNegative(OtherThreadInstantiationExpr),
+ NotTooLarge(OtherThreadInstantiationExpr))
+ ),
+ Expr.Neq(ThreadInstantiationExpr, OtherThreadInstantiationExpr)),
+ ti.VisitExpr(BarrierInvariant)))));
+ }
+ }
+ return result;
+ }
+
+
+ }
+}
diff --git a/Source/GPUVerify/GPUVerifier.cs b/Source/GPUVerify/GPUVerifier.cs
index d2ae0ad8..216954c5 100644
--- a/Source/GPUVerify/GPUVerifier.cs
+++ b/Source/GPUVerify/GPUVerifier.cs
@@ -1,2205 +1,2284 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.IO;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-
-namespace GPUVerify
-{
- class GPUVerifier : CheckingContext
- {
- public string outputFilename;
- public Program Program;
- public ResolutionContext ResContext;
-
- public Procedure KernelProcedure;
- public Implementation KernelImplementation;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie;
+using Microsoft.Basetypes;
+
+namespace GPUVerify
+{
+ class GPUVerifier : CheckingContext
+ {
+ public string outputFilename;
+ public Program Program;
+ public ResolutionContext ResContext;
+
+ public Procedure KernelProcedure;
+ public Implementation KernelImplementation;
public Procedure BarrierProcedure;
-
- public IKernelArrayInfo KernelArrayInfo = new KernelArrayInfoLists();
-
- private HashSet<string> ReservedNames = new HashSet<string>();
-
- internal HashSet<string> OnlyThread1 = new HashSet<string>();
- internal HashSet<string> OnlyThread2 = new HashSet<string>();
-
- private int TempCounter = 0;
-
- internal const string LOCAL_ID_X_STRING = "local_id_x";
- internal const string LOCAL_ID_Y_STRING = "local_id_y";
- internal const string LOCAL_ID_Z_STRING = "local_id_z";
-
- internal static Constant _X = null;
- internal static Constant _Y = null;
- internal static Constant _Z = null;
-
- internal const string GROUP_SIZE_X_STRING = "group_size_x";
- internal const string GROUP_SIZE_Y_STRING = "group_size_y";
- internal const string GROUP_SIZE_Z_STRING = "group_size_z";
-
- internal static Constant _GROUP_SIZE_X = null;
- internal static Constant _GROUP_SIZE_Y = null;
- internal static Constant _GROUP_SIZE_Z = null;
-
- internal const string GROUP_ID_X_STRING = "group_id_x";
- internal const string GROUP_ID_Y_STRING = "group_id_y";
- internal const string GROUP_ID_Z_STRING = "group_id_z";
-
- internal static Constant _GROUP_X = null;
- internal static Constant _GROUP_Y = null;
- internal static Constant _GROUP_Z = null;
-
- internal const string NUM_GROUPS_X_STRING = "num_groups_x";
- internal const string NUM_GROUPS_Y_STRING = "num_groups_y";
- internal const string NUM_GROUPS_Z_STRING = "num_groups_z";
-
- internal static Constant _NUM_GROUPS_X = null;
- internal static Constant _NUM_GROUPS_Y = null;
- internal static Constant _NUM_GROUPS_Z = null;
-
- public IRaceInstrumenter RaceInstrumenter;
-
- public UniformityAnalyser uniformityAnalyser;
- public MayBePowerOfTwoAnalyser mayBePowerOfTwoAnalyser;
- public LiveVariableAnalyser liveVariableAnalyser;
- public ArrayControlFlowAnalyser arrayControlFlowAnalyser;
- public Dictionary<Implementation, VariableDefinitionAnalysis> varDefAnalyses;
- public Dictionary<Implementation, ReducedStrengthAnalysis> reducedStrengthAnalyses;
-
- public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter) : this(filename, program, rc, raceInstrumenter, false)
- {
- }
-
- public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter, bool skipCheck)
- : base((IErrorSink)null)
- {
- this.outputFilename = filename;
- this.Program = program;
- this.ResContext = rc;
- this.RaceInstrumenter = raceInstrumenter;
- if(!skipCheck)
- CheckWellFormedness();
- }
-
- public void setRaceInstrumenter(IRaceInstrumenter ri)
- {
- this.RaceInstrumenter = ri;
- }
-
- private void CheckWellFormedness()
- {
- int errorCount = Check();
- if (errorCount != 0)
- {
- Console.WriteLine("{0} GPUVerify format errors detected in {1}", errorCount, CommandLineOptions.inputFiles[CommandLineOptions.inputFiles.Count - 1]);
- Environment.Exit(1);
- }
- }
-
- private Procedure CheckExactlyOneKernelProcedure()
- {
- var p = CheckSingleInstanceOfAttributedProcedure("kernel");
- if (p == null)
- {
- Error(Program, "\"kernel\" attribute has not been specified for any procedure. You must mark exactly one procedure with this attribute");
- }
-
- return p;
- }
-
- private Procedure FindOrCreateBarrierProcedure()
- {
- var p = CheckSingleInstanceOfAttributedProcedure("barrier");
- if (p == null)
- {
- p = new Procedure(Token.NoToken, "barrier", new TypeVariableSeq(),
- new VariableSeq(new Variable[] {
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__local_fence", new BvType(1)), true),
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__global_fence", new BvType(1)), true) }),
- new VariableSeq(),
- new RequiresSeq(), new IdentifierExprSeq(),
- new EnsuresSeq(),
- new QKeyValue(Token.NoToken, "barrier", new List<object>(), null));
- Program.TopLevelDeclarations.Add(p);
- ResContext.AddProcedure(p);
- }
- return p;
- }
-
- private Procedure CheckSingleInstanceOfAttributedProcedure(string attribute)
- {
- Procedure attributedProcedure = null;
-
- foreach (Declaration decl in Program.TopLevelDeclarations)
- {
- if (!QKeyValue.FindBoolAttribute(decl.Attributes, attribute))
- {
- continue;
- }
-
- if (decl is Implementation)
- {
- continue;
- }
-
- if (decl is Procedure)
- {
- if (attributedProcedure == null)
- {
- attributedProcedure = decl as Procedure;
- }
- else
- {
- Error(decl, "\"{0}\" attribute specified for procedure {1}, but it has already been specified for procedure {2}", attribute, (decl as Procedure).Name, attributedProcedure.Name);
- }
-
- }
- else
- {
- Error(decl, "\"{0}\" attribute can only be applied to a procedure", attribute);
- }
- }
-
- return attributedProcedure;
- }
-
- private void CheckLocalVariables()
- {
- foreach (LocalVariable LV in KernelImplementation.LocVars)
- {
- if (QKeyValue.FindBoolAttribute(LV.Attributes, "group_shared"))
- {
- Error(LV.tok, "Local variable must not be marked 'group_shared' -- promote the variable to global scope");
- }
- }
- }
-
-
- private void ReportMultipleAttributeError(string attribute, IToken first, IToken second)
- {
- Error(
- second,
- "Can only have one {0} attribute, but previously saw this attribute at ({1}, {2})",
- attribute,
- first.filename,
- first.line, first.col - 1);
- }
-
- private bool setConstAttributeField(Constant constInProgram, string attr, ref Constant constFieldRef)
- {
- if (QKeyValue.FindBoolAttribute(constInProgram.Attributes, attr))
- {
- if (constFieldRef != null)
- {
- ReportMultipleAttributeError(attr, constFieldRef.tok, constInProgram.tok);
- return false;
- }
- CheckSpecialConstantType(constInProgram);
- constFieldRef = constInProgram;
- }
- return true;
- }
-
- private void MaybeCreateAttributedConst(string attr, ref Constant constFieldRef)
- {
- if (constFieldRef == null)
- {
- constFieldRef = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, attr, Microsoft.Boogie.Type.GetBvType(32)), /*unique=*/false);
- constFieldRef.AddAttribute(attr);
- Program.TopLevelDeclarations.Add(constFieldRef);
- }
- }
-
- private bool FindNonLocalVariables()
- {
- bool success = true;
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (D is Variable &&
- (D as Variable).IsMutable &&
- (D as Variable).TypedIdent.Type is MapType &&
- !ReservedNames.Contains((D as Variable).Name))
- {
- if (QKeyValue.FindBoolAttribute(D.Attributes, "group_shared"))
- {
- KernelArrayInfo.getGroupSharedArrays().Add(D as Variable);
- }
- else if (QKeyValue.FindBoolAttribute(D.Attributes, "global"))
- {
- KernelArrayInfo.getGlobalArrays().Add(D as Variable);
- }
- else
- {
- KernelArrayInfo.getPrivateArrays().Add(D as Variable);
- }
- }
- else if (D is Constant)
- {
- Constant C = D as Constant;
-
- success &= setConstAttributeField(C, LOCAL_ID_X_STRING, ref _X);
- success &= setConstAttributeField(C, LOCAL_ID_Y_STRING, ref _Y);
- success &= setConstAttributeField(C, LOCAL_ID_Z_STRING, ref _Z);
-
- success &= setConstAttributeField(C, GROUP_SIZE_X_STRING, ref _GROUP_SIZE_X);
- success &= setConstAttributeField(C, GROUP_SIZE_Y_STRING, ref _GROUP_SIZE_Y);
- success &= setConstAttributeField(C, GROUP_SIZE_Z_STRING, ref _GROUP_SIZE_Z);
-
- success &= setConstAttributeField(C, GROUP_ID_X_STRING, ref _GROUP_X);
- success &= setConstAttributeField(C, GROUP_ID_Y_STRING, ref _GROUP_Y);
- success &= setConstAttributeField(C, GROUP_ID_Z_STRING, ref _GROUP_Z);
-
- success &= setConstAttributeField(C, NUM_GROUPS_X_STRING, ref _NUM_GROUPS_X);
- success &= setConstAttributeField(C, NUM_GROUPS_Y_STRING, ref _NUM_GROUPS_Y);
- success &= setConstAttributeField(C, NUM_GROUPS_Z_STRING, ref _NUM_GROUPS_Z);
-
-
- }
- }
-
- MaybeCreateAttributedConst(LOCAL_ID_X_STRING, ref _X);
- MaybeCreateAttributedConst(LOCAL_ID_Y_STRING, ref _Y);
- MaybeCreateAttributedConst(LOCAL_ID_Z_STRING, ref _Z);
-
- MaybeCreateAttributedConst(GROUP_SIZE_X_STRING, ref _GROUP_SIZE_X);
- MaybeCreateAttributedConst(GROUP_SIZE_Y_STRING, ref _GROUP_SIZE_Y);
- MaybeCreateAttributedConst(GROUP_SIZE_Z_STRING, ref _GROUP_SIZE_Z);
-
- MaybeCreateAttributedConst(GROUP_ID_X_STRING, ref _GROUP_X);
- MaybeCreateAttributedConst(GROUP_ID_Y_STRING, ref _GROUP_Y);
- MaybeCreateAttributedConst(GROUP_ID_Z_STRING, ref _GROUP_Z);
-
- MaybeCreateAttributedConst(NUM_GROUPS_X_STRING, ref _NUM_GROUPS_X);
- MaybeCreateAttributedConst(NUM_GROUPS_Y_STRING, ref _NUM_GROUPS_Y);
- MaybeCreateAttributedConst(NUM_GROUPS_Z_STRING, ref _NUM_GROUPS_Z);
-
- return success;
- }
-
- private void CheckSpecialConstantType(Constant C)
- {
- if (!(C.TypedIdent.Type.Equals(Microsoft.Boogie.Type.Int) || C.TypedIdent.Type.Equals(Microsoft.Boogie.Type.GetBvType(32))))
- {
- Error(C.tok, "Special constant '" + C.Name + "' must have type 'int' or 'bv32'");
- }
- }
-
- private void GetKernelImplementation()
- {
- foreach (Declaration decl in Program.TopLevelDeclarations)
- {
- if (!(decl is Implementation))
- {
- continue;
- }
-
- Implementation Impl = decl as Implementation;
-
- if (Impl.Proc == KernelProcedure)
- {
- KernelImplementation = Impl;
- break;
- }
-
- }
-
- if (KernelImplementation == null)
- {
- Error(Token.NoToken, "*** Error: no implementation of kernel procedure");
- }
- }
-
-
-
-
- protected virtual void CheckKernelImplementation()
- {
- CheckKernelParameters();
- GetKernelImplementation();
-
- if (KernelImplementation == null)
- {
- return;
- }
-
- CheckLocalVariables();
- CheckNoReturns();
- }
-
- private void CheckNoReturns()
- {
- // TODO!
- }
-
- internal void preProcess()
- {
- RemoveRedundantReturns();
-
- RemoveElseIfs();
-
- PullOutNonLocalAccesses();
- }
-
- private void MergeBlocksIntoPredecessors()
- {
- foreach (var impl in Program.TopLevelDeclarations.OfType<Implementation>())
- VC.VCGen.MergeBlocksIntoPredecessors(Program, impl);
- }
-
- internal void doit()
- {
- File.Delete(Path.GetFileNameWithoutExtension(CommandLineOptions.inputFiles[0]) + ".loc");
- if (CommandLineOptions.Unstructured)
- {
- Microsoft.Boogie.CommandLineOptions.Clo.PrintUnstructured = 2;
- }
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_original");
- }
-
- preProcess();
-
- if (CommandLineOptions.ShowStages) {
- emitProgram(outputFilename + "_preprocessed");
- }
-
- DoLiveVariableAnalysis();
-
- DoUniformityAnalysis();
-
- DoVariableDefinitionAnalysis();
-
- DoReducedStrengthAnalysis();
-
- DoMayBePowerOfTwoAnalysis();
-
- DoArrayControlFlowAnalysis();
-
- if (CommandLineOptions.Inference)
- {
- foreach (var impl in Program.TopLevelDeclarations.OfType<Implementation>().ToList())
- {
- LoopInvariantGenerator.PreInstrument(this, impl);
- }
-
- if (CommandLineOptions.ShowStages) {
- emitProgram(outputFilename + "_pre_inference");
- }
-
- }
-
- RaceInstrumenter.AddRaceCheckingInstrumentation();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_instrumented");
- }
-
- AbstractSharedState();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_abstracted");
- }
-
- MergeBlocksIntoPredecessors();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_merged_pre_predication");
- }
-
- MakeKernelPredicated();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_predicated");
- }
-
- MergeBlocksIntoPredecessors();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_merged_post_predication");
- }
-
- MakeKernelDualised();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_dualised");
- }
-
- RaceInstrumenter.AddRaceCheckingDeclarations();
-
- GenerateBarrierImplementation();
-
- GenerateStandardKernelContract();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_ready_to_verify");
- }
-
- if (CommandLineOptions.Inference)
- {
- ComputeInvariant();
- }
-
- emitProgram(outputFilename);
-
- }
-
- private void DoMayBePowerOfTwoAnalysis()
- {
- mayBePowerOfTwoAnalyser = new MayBePowerOfTwoAnalyser(this);
- mayBePowerOfTwoAnalyser.Analyse();
- }
-
- private void DoArrayControlFlowAnalysis()
- {
- arrayControlFlowAnalyser = new ArrayControlFlowAnalyser(this);
- arrayControlFlowAnalyser.Analyse();
- }
-
- private void DoUniformityAnalysis()
- {
- uniformityAnalyser = new UniformityAnalyser(this);
- uniformityAnalyser.Analyse();
- }
-
- private void DoLiveVariableAnalysis()
- {
- liveVariableAnalyser = new LiveVariableAnalyser(this);
- liveVariableAnalyser.Analyse();
- }
-
- private void DoVariableDefinitionAnalysis()
- {
- varDefAnalyses = Program.TopLevelDeclarations
- .OfType<Implementation>()
- .ToDictionary(i => i, i => VariableDefinitionAnalysis.Analyse(this, i));
- }
-
- private void DoReducedStrengthAnalysis()
- {
- reducedStrengthAnalyses = Program.TopLevelDeclarations
- .OfType<Implementation>()
- .ToDictionary(i => i, i => ReducedStrengthAnalysis.Analyse(this, i));
- }
-
- private void emitProgram(string filename)
- {
- using (TokenTextWriter writer = new TokenTextWriter(filename + ".bpl"))
- {
- Program.Emit(writer);
- }
- }
-
- private void ComputeInvariant()
- {
- for (int i = 0; i < Program.TopLevelDeclarations.Count; i++)
- {
- if (Program.TopLevelDeclarations[i] is Implementation)
- {
-
- Implementation Impl = Program.TopLevelDeclarations[i] as Implementation;
-
- List<Expr> UserSuppliedInvariants = GetUserSuppliedInvariants(Impl.Name);
-
- LoopInvariantGenerator.PostInstrument(this, Impl, UserSuppliedInvariants);
-
- Procedure Proc = Impl.Proc;
-
- if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
-
- if (Proc == KernelProcedure)
- {
- continue;
- }
-
- AddCandidateRequires(Proc);
- RaceInstrumenter.AddRaceCheckingCandidateRequires(Proc);
- AddUserSuppliedCandidateRequires(Proc, UserSuppliedInvariants);
-
- AddCandidateEnsures(Proc);
- RaceInstrumenter.AddRaceCheckingCandidateEnsures(Proc);
- AddUserSuppliedCandidateEnsures(Proc, UserSuppliedInvariants);
-
- }
-
-
- }
-
- }
-
- private void AddCandidateEnsures(Procedure Proc)
- {
- HashSet<string> names = new HashSet<String>();
- foreach (Variable v in Proc.OutParams)
- {
- names.Add(StripThreadIdentifier(v.Name));
- }
-
- foreach (string name in names)
- {
- if (!uniformityAnalyser.IsUniform(Proc.Name, name))
- {
- AddEqualityCandidateEnsures(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
- }
- }
-
- }
-
- private void AddCandidateRequires(Procedure Proc)
- {
- HashSet<string> names = new HashSet<String>();
- foreach (Variable v in Proc.InParams)
- {
- names.Add(StripThreadIdentifier(v.Name));
- }
-
- foreach (string name in names)
- {
-
- if (IsPredicateOrTemp(name))
- {
- Debug.Assert(name.Equals("_P"));
- Debug.Assert(!uniformityAnalyser.IsUniform(Proc.Name));
- AddCandidateRequires(Proc, Expr.Eq(
- new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name + "$1", Microsoft.Boogie.Type.Bool))),
- new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name + "$2", Microsoft.Boogie.Type.Bool)))
- ));
- }
- else
- {
- if (!uniformityAnalyser.IsUniform(Proc.Name, name))
- {
- if (!uniformityAnalyser.IsUniform(Proc.Name))
- {
- AddPredicatedEqualityCandidateRequires(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
- }
- AddEqualityCandidateRequires(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
- }
- }
- }
-
- }
-
- private void AddPredicatedEqualityCandidateRequires(Procedure Proc, Variable v)
- {
- AddCandidateRequires(Proc, Expr.Imp(
- Expr.And(
- new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, "_P$1", Microsoft.Boogie.Type.Bool))),
- new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, "_P$2", Microsoft.Boogie.Type.Bool)))
- ),
- Expr.Eq(
- new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
- )
- ));
- }
-
- private void AddEqualityCandidateRequires(Procedure Proc, Variable v)
- {
- AddCandidateRequires(Proc,
- Expr.Eq(
- new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
- )
- );
- }
-
- private void AddEqualityCandidateEnsures(Procedure Proc, Variable v)
- {
- AddCandidateEnsures(Proc,
- Expr.Eq(
- new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
- ));
- }
-
-
- private void AddUserSuppliedCandidateRequires(Procedure Proc, List<Expr> UserSuppliedInvariants)
- {
- foreach (Expr e in UserSuppliedInvariants)
- {
- Requires r = new Requires(false, e);
- Proc.Requires.Add(r);
- bool OK = ProgramIsOK(Proc);
- Proc.Requires.Remove(r);
- if (OK)
- {
- AddCandidateRequires(Proc, e);
- }
- }
- }
-
- private void AddUserSuppliedCandidateEnsures(Procedure Proc, List<Expr> UserSuppliedInvariants)
- {
- foreach (Expr e in UserSuppliedInvariants)
- {
- Ensures ens = new Ensures(false, e);
- Proc.Ensures.Add(ens);
- bool OK = ProgramIsOK(Proc);
- Proc.Ensures.Remove(ens);
- if (OK)
- {
- AddCandidateEnsures(Proc, e);
- }
- }
- }
-
-
-
- internal void AddCandidateRequires(Procedure Proc, Expr e)
- {
- Constant ExistentialBooleanConstant = Program.MakeExistentialBoolean();
- IdentifierExpr ExistentialBoolean = new IdentifierExpr(Proc.tok, ExistentialBooleanConstant);
- Proc.Requires.Add(new Requires(false, Expr.Imp(ExistentialBoolean, e)));
- }
-
- internal void AddCandidateEnsures(Procedure Proc, Expr e)
- {
- Constant ExistentialBooleanConstant = Program.MakeExistentialBoolean();
- IdentifierExpr ExistentialBoolean = new IdentifierExpr(Proc.tok, ExistentialBooleanConstant);
- Proc.Ensures.Add(new Ensures(false, Expr.Imp(ExistentialBoolean, e)));
- }
-
- private List<Expr> GetUserSuppliedInvariants(string ProcedureName)
- {
- List<Expr> result = new List<Expr>();
-
- if (CommandLineOptions.invariantsFile == null)
- {
- return result;
- }
-
- StreamReader sr = new StreamReader(new FileStream(CommandLineOptions.invariantsFile, FileMode.Open, FileAccess.Read));
- string line;
- int lineNumber = 1;
- while ((line = sr.ReadLine()) != null)
- {
- string[] components = line.Split(':');
-
- if (components.Length != 1 && components.Length != 2)
- {
- Console.WriteLine("Ignoring badly formed candidate invariant '" + line + "' at '" + CommandLineOptions.invariantsFile + "' line " + lineNumber);
- continue;
- }
-
- if (components.Length == 2)
- {
- if (!components[0].Trim().Equals(ProcedureName))
- {
- continue;
- }
-
- line = components[1];
- }
-
- string temp_program_text = "axiom (" + line + ");";
- TokenTextWriter writer = new TokenTextWriter("temp_out.bpl");
- writer.WriteLine(temp_program_text);
- writer.Close();
-
- Program temp_program = GPUVerify.ParseBoogieProgram(new List<string>(new string[] { "temp_out.bpl" }), false);
-
- if (null == temp_program)
- {
- Console.WriteLine("Ignoring badly formed candidate invariant '" + line + "' at '" + CommandLineOptions.invariantsFile + "' line " + lineNumber);
- }
- else
- {
- Debug.Assert(temp_program.TopLevelDeclarations[0] is Axiom);
- result.Add((temp_program.TopLevelDeclarations[0] as Axiom).Expr);
- }
-
- lineNumber++;
- }
-
- return result;
- }
-
- internal bool ContainsNamedVariable(HashSet<Variable> variables, string name)
- {
- foreach(Variable v in variables)
- {
- if(StripThreadIdentifier(v.Name) == name)
- {
- return true;
- }
- }
- return false;
- }
-
- internal static bool IsPredicate(string v) {
- if (v.Length < 2) {
- return false;
- }
- if (!v.Substring(0, 1).Equals("p")) {
- return false;
- }
- for (int i = 1; i < v.Length; i++) {
- if (!Char.IsDigit(v.ToCharArray()[i])) {
- return false;
- }
+
+ public IKernelArrayInfo KernelArrayInfo = new KernelArrayInfoLists();
+
+ private HashSet<string> ReservedNames = new HashSet<string>();
+
+ internal HashSet<string> OnlyThread1 = new HashSet<string>();
+ internal HashSet<string> OnlyThread2 = new HashSet<string>();
+
+ private int TempCounter = 0;
+
+ internal const string LOCAL_ID_X_STRING = "local_id_x";
+ internal const string LOCAL_ID_Y_STRING = "local_id_y";
+ internal const string LOCAL_ID_Z_STRING = "local_id_z";
+
+ internal static Constant _X = null;
+ internal static Constant _Y = null;
+ internal static Constant _Z = null;
+
+ internal const string GROUP_SIZE_X_STRING = "group_size_x";
+ internal const string GROUP_SIZE_Y_STRING = "group_size_y";
+ internal const string GROUP_SIZE_Z_STRING = "group_size_z";
+
+ internal static Constant _GROUP_SIZE_X = null;
+ internal static Constant _GROUP_SIZE_Y = null;
+ internal static Constant _GROUP_SIZE_Z = null;
+
+ internal const string GROUP_ID_X_STRING = "group_id_x";
+ internal const string GROUP_ID_Y_STRING = "group_id_y";
+ internal const string GROUP_ID_Z_STRING = "group_id_z";
+
+ internal static Constant _GROUP_X = null;
+ internal static Constant _GROUP_Y = null;
+ internal static Constant _GROUP_Z = null;
+
+ internal const string NUM_GROUPS_X_STRING = "num_groups_x";
+ internal const string NUM_GROUPS_Y_STRING = "num_groups_y";
+ internal const string NUM_GROUPS_Z_STRING = "num_groups_z";
+
+ internal static Constant _NUM_GROUPS_X = null;
+ internal static Constant _NUM_GROUPS_Y = null;
+ internal static Constant _NUM_GROUPS_Z = null;
+
+ public IRaceInstrumenter RaceInstrumenter;
+
+ public UniformityAnalyser uniformityAnalyser;
+ public MayBePowerOfTwoAnalyser mayBePowerOfTwoAnalyser;
+ public LiveVariableAnalyser liveVariableAnalyser;
+ public ArrayControlFlowAnalyser arrayControlFlowAnalyser;
+ public Dictionary<Implementation, VariableDefinitionAnalysis> varDefAnalyses;
+ public Dictionary<Implementation, ReducedStrengthAnalysis> reducedStrengthAnalyses;
+
+ public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter) : this(filename, program, rc, raceInstrumenter, false)
+ {
+ }
+
+ public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter, bool skipCheck)
+ : base((IErrorSink)null)
+ {
+ this.outputFilename = filename;
+ this.Program = program;
+ this.ResContext = rc;
+ this.RaceInstrumenter = raceInstrumenter;
+ if(!skipCheck)
+ CheckWellFormedness();
+ }
+
+ public void setRaceInstrumenter(IRaceInstrumenter ri)
+ {
+ this.RaceInstrumenter = ri;
+ }
+
+ private void CheckWellFormedness()
+ {
+ int errorCount = Check();
+ if (errorCount != 0)
+ {
+ Console.WriteLine("{0} GPUVerify format errors detected in {1}", errorCount, CommandLineOptions.inputFiles[CommandLineOptions.inputFiles.Count - 1]);
+ Environment.Exit(1);
+ }
+ }
+
+ private Procedure CheckExactlyOneKernelProcedure()
+ {
+ var p = CheckSingleInstanceOfAttributedProcedure("kernel");
+ if (p == null)
+ {
+ Error(Program, "\"kernel\" attribute has not been specified for any procedure. You must mark exactly one procedure with this attribute");
+ }
+
+ return p;
+ }
+
+ private Procedure FindOrCreateBarrierProcedure()
+ {
+ var p = CheckSingleInstanceOfAttributedProcedure("barrier");
+ if (p == null)
+ {
+ p = new Procedure(Token.NoToken, "barrier", new TypeVariableSeq(),
+ new VariableSeq(new Variable[] {
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__local_fence", new BvType(1)), true),
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__global_fence", new BvType(1)), true) }),
+ new VariableSeq(),
+ new RequiresSeq(), new IdentifierExprSeq(),
+ new EnsuresSeq(),
+ new QKeyValue(Token.NoToken, "barrier", new List<object>(), null));
+ Program.TopLevelDeclarations.Add(p);
+ ResContext.AddProcedure(p);
+ }
+ return p;
+ }
+
+ private Procedure FindOrCreateBarrierInvariantProcedure() {
+ var p = CheckSingleInstanceOfAttributedProcedure("barrier_invariant");
+ if (p == null) {
+ p = new Procedure(Token.NoToken, "barrier_invariant", new TypeVariableSeq(),
+ new VariableSeq(new Variable[] {
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__cond",
+ Microsoft.Boogie.Type.Bool), true)
+ }),
+ new VariableSeq(), new RequiresSeq(), new IdentifierExprSeq(),
+ new EnsuresSeq(),
+ new QKeyValue(Token.NoToken, "barrier_invariant", new List<object>(), null));
+ Program.TopLevelDeclarations.Add(p);
+ ResContext.AddProcedure(p);
}
- return true;
- }
-
- internal static bool IsPredicateOrTemp(string lv) {
-
- // We should improve this by having a general convention
- // for names of temporary or predicate variables
-
- if (lv.Length >= 2) {
- if (lv.Substring(0, 1).Equals("p") || lv.Substring(0, 1).Equals("v")) {
- for (int i = 1; i < lv.Length; i++) {
- if (!Char.IsDigit(lv.ToCharArray()[i])) {
- return false;
- }
- }
- return true;
- }
-
+ return p;
+ }
+
+ private Procedure FindOrCreateBarrierInvariantInstantiationProcedure() {
+ var p = CheckSingleInstanceOfAttributedProcedure("barrier_invariant_instantiation");
+ if (p == null) {
+ p = new Procedure(Token.NoToken, "barrier_invariant_instantiation", new TypeVariableSeq(),
+ new VariableSeq(new Variable[] {
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__t1",
+ new BvType(32)), true),
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__t2",
+ new BvType(32)), true)
+ }),
+ new VariableSeq(), new RequiresSeq(), new IdentifierExprSeq(),
+ new EnsuresSeq(),
+ new QKeyValue(Token.NoToken, "barrier_invariant_instantiation", new List<object>(), null));
+ Program.TopLevelDeclarations.Add(p);
+ ResContext.AddProcedure(p);
}
+ return p;
+ }
+
+ private Procedure CheckSingleInstanceOfAttributedProcedure(string attribute)
+ {
+ Procedure attributedProcedure = null;
+
+ foreach (Declaration decl in Program.TopLevelDeclarations)
+ {
+ if (!QKeyValue.FindBoolAttribute(decl.Attributes, attribute))
+ {
+ continue;
+ }
+
+ if (decl is Implementation)
+ {
+ continue;
+ }
+
+ if (decl is Procedure)
+ {
+ if (attributedProcedure == null)
+ {
+ attributedProcedure = decl as Procedure;
+ }
+ else
+ {
+ Error(decl, "\"{0}\" attribute specified for procedure {1}, but it has already been specified for procedure {2}", attribute, (decl as Procedure).Name, attributedProcedure.Name);
+ }
+
+ }
+ else
+ {
+ Error(decl, "\"{0}\" attribute can only be applied to a procedure", attribute);
+ }
+ }
+
+ return attributedProcedure;
+ }
+
+ private void CheckLocalVariables()
+ {
+ foreach (LocalVariable LV in KernelImplementation.LocVars)
+ {
+ if (QKeyValue.FindBoolAttribute(LV.Attributes, "group_shared"))
+ {
+ Error(LV.tok, "Local variable must not be marked 'group_shared' -- promote the variable to global scope");
+ }
+ }
+ }
+
+
+ private void ReportMultipleAttributeError(string attribute, IToken first, IToken second)
+ {
+ Error(
+ second,
+ "Can only have one {0} attribute, but previously saw this attribute at ({1}, {2})",
+ attribute,
+ first.filename,
+ first.line, first.col - 1);
+ }
+
+ private bool setConstAttributeField(Constant constInProgram, string attr, ref Constant constFieldRef)
+ {
+ if (QKeyValue.FindBoolAttribute(constInProgram.Attributes, attr))
+ {
+ if (constFieldRef != null)
+ {
+ ReportMultipleAttributeError(attr, constFieldRef.tok, constInProgram.tok);
+ return false;
+ }
+ CheckSpecialConstantType(constInProgram);
+ constFieldRef = constInProgram;
+ }
+ return true;
+ }
+
+ private void MaybeCreateAttributedConst(string attr, ref Constant constFieldRef)
+ {
+ if (constFieldRef == null)
+ {
+ constFieldRef = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, attr, Microsoft.Boogie.Type.GetBvType(32)), /*unique=*/false);
+ constFieldRef.AddAttribute(attr);
+ Program.TopLevelDeclarations.Add(constFieldRef);
+ }
+ }
+
+ private bool FindNonLocalVariables()
+ {
+ bool success = true;
+ foreach (Declaration D in Program.TopLevelDeclarations)
+ {
+ if (D is Variable &&
+ (D as Variable).IsMutable &&
+ (D as Variable).TypedIdent.Type is MapType &&
+ !ReservedNames.Contains((D as Variable).Name))
+ {
+ if (QKeyValue.FindBoolAttribute(D.Attributes, "group_shared"))
+ {
+ KernelArrayInfo.getGroupSharedArrays().Add(D as Variable);
+ }
+ else if (QKeyValue.FindBoolAttribute(D.Attributes, "global"))
+ {
+ KernelArrayInfo.getGlobalArrays().Add(D as Variable);
+ }
+ else
+ {
+ KernelArrayInfo.getPrivateArrays().Add(D as Variable);
+ }
+ }
+ else if (D is Constant)
+ {
+ Constant C = D as Constant;
+
+ success &= setConstAttributeField(C, LOCAL_ID_X_STRING, ref _X);
+ success &= setConstAttributeField(C, LOCAL_ID_Y_STRING, ref _Y);
+ success &= setConstAttributeField(C, LOCAL_ID_Z_STRING, ref _Z);
+
+ success &= setConstAttributeField(C, GROUP_SIZE_X_STRING, ref _GROUP_SIZE_X);
+ success &= setConstAttributeField(C, GROUP_SIZE_Y_STRING, ref _GROUP_SIZE_Y);
+ success &= setConstAttributeField(C, GROUP_SIZE_Z_STRING, ref _GROUP_SIZE_Z);
+
+ success &= setConstAttributeField(C, GROUP_ID_X_STRING, ref _GROUP_X);
+ success &= setConstAttributeField(C, GROUP_ID_Y_STRING, ref _GROUP_Y);
+ success &= setConstAttributeField(C, GROUP_ID_Z_STRING, ref _GROUP_Z);
+
+ success &= setConstAttributeField(C, NUM_GROUPS_X_STRING, ref _NUM_GROUPS_X);
+ success &= setConstAttributeField(C, NUM_GROUPS_Y_STRING, ref _NUM_GROUPS_Y);
+ success &= setConstAttributeField(C, NUM_GROUPS_Z_STRING, ref _NUM_GROUPS_Z);
+
+
+ }
+ }
+
+ MaybeCreateAttributedConst(LOCAL_ID_X_STRING, ref _X);
+ MaybeCreateAttributedConst(LOCAL_ID_Y_STRING, ref _Y);
+ MaybeCreateAttributedConst(LOCAL_ID_Z_STRING, ref _Z);
+
+ MaybeCreateAttributedConst(GROUP_SIZE_X_STRING, ref _GROUP_SIZE_X);
+ MaybeCreateAttributedConst(GROUP_SIZE_Y_STRING, ref _GROUP_SIZE_Y);
+ MaybeCreateAttributedConst(GROUP_SIZE_Z_STRING, ref _GROUP_SIZE_Z);
+
+ MaybeCreateAttributedConst(GROUP_ID_X_STRING, ref _GROUP_X);
+ MaybeCreateAttributedConst(GROUP_ID_Y_STRING, ref _GROUP_Y);
+ MaybeCreateAttributedConst(GROUP_ID_Z_STRING, ref _GROUP_Z);
+
+ MaybeCreateAttributedConst(NUM_GROUPS_X_STRING, ref _NUM_GROUPS_X);
+ MaybeCreateAttributedConst(NUM_GROUPS_Y_STRING, ref _NUM_GROUPS_Y);
+ MaybeCreateAttributedConst(NUM_GROUPS_Z_STRING, ref _NUM_GROUPS_Z);
+
+ return success;
+ }
+
+ private void CheckSpecialConstantType(Constant C)
+ {
+ if (!(C.TypedIdent.Type.Equals(Microsoft.Boogie.Type.Int) || C.TypedIdent.Type.Equals(Microsoft.Boogie.Type.GetBvType(32))))
+ {
+ Error(C.tok, "Special constant '" + C.Name + "' must have type 'int' or 'bv32'");
+ }
+ }
+
+ private void GetKernelImplementation()
+ {
+ foreach (Declaration decl in Program.TopLevelDeclarations)
+ {
+ if (!(decl is Implementation))
+ {
+ continue;
+ }
+
+ Implementation Impl = decl as Implementation;
+
+ if (Impl.Proc == KernelProcedure)
+ {
+ KernelImplementation = Impl;
+ break;
+ }
+
+ }
+
+ if (KernelImplementation == null)
+ {
+ Error(Token.NoToken, "*** Error: no implementation of kernel procedure");
+ }
+ }
+
+
+
+
+ protected virtual void CheckKernelImplementation()
+ {
+ CheckKernelParameters();
+ GetKernelImplementation();
+
+ if (KernelImplementation == null)
+ {
+ return;
+ }
+
+ CheckLocalVariables();
+ CheckNoReturns();
+ }
+
+ private void CheckNoReturns()
+ {
+ // TODO!
+ }
+
+ internal void preProcess()
+ {
+ RemoveRedundantReturns();
+
+ RemoveElseIfs();
+
+ PullOutNonLocalAccesses();
+ }
+
+ private void MergeBlocksIntoPredecessors()
+ {
+ foreach (var impl in Program.TopLevelDeclarations.OfType<Implementation>())
+ VC.VCGen.MergeBlocksIntoPredecessors(Program, impl, uniformityAnalyser);
+ }
+
+ internal void doit()
+ {
+ File.Delete(Path.GetFileNameWithoutExtension(CommandLineOptions.inputFiles[0]) + ".loc");
+ if (CommandLineOptions.Unstructured)
+ {
+ Microsoft.Boogie.CommandLineOptions.Clo.PrintUnstructured = 2;
+ }
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_original");
+ }
+
+ preProcess();
+
+ if (CommandLineOptions.ShowStages) {
+ emitProgram(outputFilename + "_preprocessed");
+ }
+
+ DoLiveVariableAnalysis();
+
+ DoUniformityAnalysis();
- if (lv.Contains("_HAVOC_")) {
- return true;
+ DoVariableDefinitionAnalysis();
+
+ DoReducedStrengthAnalysis();
+
+ DoMayBePowerOfTwoAnalysis();
+
+ DoArrayControlFlowAnalysis();
+
+ if (CommandLineOptions.Inference)
+ {
+ foreach (var proc in Program.TopLevelDeclarations.OfType<Procedure>().ToList())
+ {
+ RaceInstrumenter.DoHoudiniPointerAnalysis(proc);
+ }
+
+ foreach (var impl in Program.TopLevelDeclarations.OfType<Implementation>().ToList())
+ {
+ LoopInvariantGenerator.PreInstrument(this, impl);
+ }
+
+ if (CommandLineOptions.ShowStages) {
+ emitProgram(outputFilename + "_pre_inference");
+ }
+
+ }
+
+ RaceInstrumenter.AddRaceCheckingInstrumentation();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_instrumented");
+ }
+
+ AbstractSharedState();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_abstracted");
+ }
+
+ MergeBlocksIntoPredecessors();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_merged_pre_predication");
+ }
+
+ MakeKernelPredicated();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_predicated");
+ }
+
+ MergeBlocksIntoPredecessors();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_merged_post_predication");
+ }
+
+ MakeKernelDualised();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_dualised");
+ }
+
+ RaceInstrumenter.AddRaceCheckingDeclarations();
+
+ GenerateBarrierImplementation();
+
+ GenerateStandardKernelContract();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_ready_to_verify");
+ }
+
+ if (CommandLineOptions.Inference)
+ {
+ ComputeInvariant();
+ }
+
+ emitProgram(outputFilename);
+
+ }
+
+ private void DoMayBePowerOfTwoAnalysis()
+ {
+ mayBePowerOfTwoAnalyser = new MayBePowerOfTwoAnalyser(this);
+ mayBePowerOfTwoAnalyser.Analyse();
+ }
+
+ private void DoArrayControlFlowAnalysis()
+ {
+ arrayControlFlowAnalyser = new ArrayControlFlowAnalyser(this);
+ arrayControlFlowAnalyser.Analyse();
+ }
+
+ private void DoUniformityAnalysis()
+ {
+ var entryPoints = new HashSet<Implementation>();
+ if (CommandLineOptions.DoUniformityAnalysis) {
+ entryPoints.Add(KernelImplementation);
+ }
+
+ var nonUniformVars = new Variable[] { _X, _Y, _Z, _GROUP_X, _GROUP_Y, _GROUP_Z };
+
+ uniformityAnalyser = new UniformityAnalyser(Program, CommandLineOptions.DoUniformityAnalysis, CommandLineOptions.Unstructured,
+ entryPoints, nonUniformVars);
+ uniformityAnalyser.Analyse();
+ }
+
+ private void DoLiveVariableAnalysis()
+ {
+ liveVariableAnalyser = new LiveVariableAnalyser(this);
+ liveVariableAnalyser.Analyse();
+ }
+
+ private void DoVariableDefinitionAnalysis()
+ {
+ varDefAnalyses = Program.TopLevelDeclarations
+ .OfType<Implementation>()
+ .ToDictionary(i => i, i => VariableDefinitionAnalysis.Analyse(this, i));
+ }
+
+ private void DoReducedStrengthAnalysis()
+ {
+ reducedStrengthAnalyses = Program.TopLevelDeclarations
+ .OfType<Implementation>()
+ .ToDictionary(i => i, i => ReducedStrengthAnalysis.Analyse(this, i));
+ }
+
+ private void emitProgram(string filename)
+ {
+ using (TokenTextWriter writer = new TokenTextWriter(filename + ".bpl"))
+ {
+ Program.Emit(writer);
+ }
+ }
+
+ private void ComputeInvariant()
+ {
+ for (int i = 0; i < Program.TopLevelDeclarations.Count; i++)
+ {
+ if (Program.TopLevelDeclarations[i] is Implementation)
+ {
+
+ Implementation Impl = Program.TopLevelDeclarations[i] as Implementation;
+
+ List<Expr> UserSuppliedInvariants = GetUserSuppliedInvariants(Impl.Name);
+
+ LoopInvariantGenerator.PostInstrument(this, Impl, UserSuppliedInvariants);
+
+ Procedure Proc = Impl.Proc;
+
+ if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
+ {
+ continue;
+ }
+
+ if (Proc == KernelProcedure)
+ {
+ continue;
+ }
+
+ AddCandidateRequires(Proc);
+ RaceInstrumenter.AddRaceCheckingCandidateRequires(Proc);
+ AddUserSuppliedCandidateRequires(Proc, UserSuppliedInvariants);
+
+ AddCandidateEnsures(Proc);
+ RaceInstrumenter.AddRaceCheckingCandidateEnsures(Proc);
+ AddUserSuppliedCandidateEnsures(Proc, UserSuppliedInvariants);
+
+ }
+
+
+ }
+
+ }
+
+ private void AddCandidateEnsures(Procedure Proc)
+ {
+ HashSet<string> names = new HashSet<String>();
+ foreach (Variable v in Proc.OutParams)
+ {
+ names.Add(StripThreadIdentifier(v.Name));
+ }
+
+ foreach (string name in names)
+ {
+ if (!uniformityAnalyser.IsUniform(Proc.Name, name))
+ {
+ AddEqualityCandidateEnsures(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
+ }
+ }
+
+ }
+
+ private void AddCandidateRequires(Procedure Proc)
+ {
+ HashSet<string> names = new HashSet<String>();
+ foreach (Variable v in Proc.InParams)
+ {
+ names.Add(StripThreadIdentifier(v.Name));
+ }
+
+ foreach (string name in names)
+ {
+
+ if (IsPredicateOrTemp(name))
+ {
+ Debug.Assert(name.Equals("_P"));
+ Debug.Assert(!uniformityAnalyser.IsUniform(Proc.Name));
+ AddCandidateRequires(Proc, Expr.Eq(
+ new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name + "$1", Microsoft.Boogie.Type.Bool))),
+ new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name + "$2", Microsoft.Boogie.Type.Bool)))
+ ));
+ }
+ else
+ {
+ if (!uniformityAnalyser.IsUniform(Proc.Name, name))
+ {
+ if (!uniformityAnalyser.IsUniform(Proc.Name))
+ {
+ AddPredicatedEqualityCandidateRequires(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
+ }
+ AddEqualityCandidateRequires(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
+ }
+ }
+ }
+
+ }
+
+ private void AddPredicatedEqualityCandidateRequires(Procedure Proc, Variable v)
+ {
+ AddCandidateRequires(Proc, Expr.Imp(
+ Expr.And(
+ new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, "_P$1", Microsoft.Boogie.Type.Bool))),
+ new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, "_P$2", Microsoft.Boogie.Type.Bool)))
+ ),
+ Expr.Eq(
+ new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
+ new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
+ )
+ ));
+ }
+
+ private void AddEqualityCandidateRequires(Procedure Proc, Variable v)
+ {
+ AddCandidateRequires(Proc,
+ Expr.Eq(
+ new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
+ new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
+ )
+ );
+ }
+
+ private void AddEqualityCandidateEnsures(Procedure Proc, Variable v)
+ {
+ AddCandidateEnsures(Proc,
+ Expr.Eq(
+ new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
+ new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
+ ));
+ }
+
+
+ private void AddUserSuppliedCandidateRequires(Procedure Proc, List<Expr> UserSuppliedInvariants)
+ {
+ foreach (Expr e in UserSuppliedInvariants)
+ {
+ Requires r = new Requires(false, e);
+ Proc.Requires.Add(r);
+ bool OK = ProgramIsOK(Proc);
+ Proc.Requires.Remove(r);
+ if (OK)
+ {
+ AddCandidateRequires(Proc, e);
+ }
+ }
+ }
+
+ private void AddUserSuppliedCandidateEnsures(Procedure Proc, List<Expr> UserSuppliedInvariants)
+ {
+ foreach (Expr e in UserSuppliedInvariants)
+ {
+ Ensures ens = new Ensures(false, e);
+ Proc.Ensures.Add(ens);
+ bool OK = ProgramIsOK(Proc);
+ Proc.Ensures.Remove(ens);
+ if (OK)
+ {
+ AddCandidateEnsures(Proc, e);
+ }
+ }
+ }
+
+
+
+ internal void AddCandidateRequires(Procedure Proc, Expr e)
+ {
+ Constant ExistentialBooleanConstant = Program.MakeExistentialBoolean();
+ IdentifierExpr ExistentialBoolean = new IdentifierExpr(Proc.tok, ExistentialBooleanConstant);
+ Proc.Requires.Add(new Requires(false, Expr.Imp(ExistentialBoolean, e)));
+ }
+
+ internal void AddCandidateEnsures(Procedure Proc, Expr e)
+ {
+ Constant ExistentialBooleanConstant = Program.MakeExistentialBoolean();
+ IdentifierExpr ExistentialBoolean = new IdentifierExpr(Proc.tok, ExistentialBooleanConstant);
+ Proc.Ensures.Add(new Ensures(false, Expr.Imp(ExistentialBoolean, e)));
+ }
+
+ private List<Expr> GetUserSuppliedInvariants(string ProcedureName)
+ {
+ List<Expr> result = new List<Expr>();
+
+ if (CommandLineOptions.invariantsFile == null)
+ {
+ return result;
+ }
+
+ StreamReader sr = new StreamReader(new FileStream(CommandLineOptions.invariantsFile, FileMode.Open, FileAccess.Read));
+ string line;
+ int lineNumber = 1;
+ while ((line = sr.ReadLine()) != null)
+ {
+ string[] components = line.Split(':');
+
+ if (components.Length != 1 && components.Length != 2)
+ {
+ Console.WriteLine("Ignoring badly formed candidate invariant '" + line + "' at '" + CommandLineOptions.invariantsFile + "' line " + lineNumber);
+ continue;
+ }
+
+ if (components.Length == 2)
+ {
+ if (!components[0].Trim().Equals(ProcedureName))
+ {
+ continue;
+ }
+
+ line = components[1];
+ }
+
+ string temp_program_text = "axiom (" + line + ");";
+ TokenTextWriter writer = new TokenTextWriter("temp_out.bpl");
+ writer.WriteLine(temp_program_text);
+ writer.Close();
+
+ Program temp_program = GPUVerify.ParseBoogieProgram(new List<string>(new string[] { "temp_out.bpl" }), false);
+
+ if (null == temp_program)
+ {
+ Console.WriteLine("Ignoring badly formed candidate invariant '" + line + "' at '" + CommandLineOptions.invariantsFile + "' line " + lineNumber);
+ }
+ else
+ {
+ Debug.Assert(temp_program.TopLevelDeclarations[0] is Axiom);
+ result.Add((temp_program.TopLevelDeclarations[0] as Axiom).Expr);
+ }
+
+ lineNumber++;
+ }
+
+ return result;
+ }
+
+ internal bool ContainsNamedVariable(HashSet<Variable> variables, string name)
+ {
+ foreach(Variable v in variables)
+ {
+ if(StripThreadIdentifier(v.Name) == name)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ internal static bool IsPredicate(string v) {
+ if (v.Length < 2) {
+ return false;
+ }
+ if (!v.Substring(0, 1).Equals("p")) {
+ return false;
+ }
+ for (int i = 1; i < v.Length; i++) {
+ if (!Char.IsDigit(v.ToCharArray()[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ internal static bool IsPredicateOrTemp(string lv) {
+
+ // We should improve this by having a general convention
+ // for names of temporary or predicate variables
+
+ if (lv.Length >= 2) {
+ if (lv.Substring(0, 1).Equals("p") || lv.Substring(0, 1).Equals("v")) {
+ for (int i = 1; i < lv.Length; i++) {
+ if (!Char.IsDigit(lv.ToCharArray()[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ }
+
+ if (lv.Contains("_HAVOC_")) {
+ return true;
+ }
+
+ return (lv.Length >= 2 && lv.Substring(0,2).Equals("_P")) ||
+ (lv.Length > 3 && lv.Substring(0,3).Equals("_LC")) ||
+ (lv.Length > 5 && lv.Substring(0,5).Equals("_temp"));
+ }
+
+
+
+
+ internal bool ProgramIsOK(Declaration d)
+ {
+ Debug.Assert(d is Procedure || d is Implementation);
+ TokenTextWriter writer = new TokenTextWriter("temp_out.bpl");
+ List<Declaration> RealDecls = Program.TopLevelDeclarations;
+ List<Declaration> TempDecls = new List<Declaration>();
+ foreach (Declaration d2 in RealDecls)
+ {
+ if (d is Procedure)
+ {
+ if ((d == d2) || !(d2 is Implementation || d2 is Procedure))
+ {
+ TempDecls.Add(d2);
+ }
+ }
+ else if (d is Implementation)
+ {
+ if ((d == d2) || !(d2 is Implementation))
+ {
+ TempDecls.Add(d2);
+ }
+ }
+ }
+ Program.TopLevelDeclarations = TempDecls;
+ Program.Emit(writer);
+ writer.Close();
+ Program.TopLevelDeclarations = RealDecls;
+ Program temp_program = GPUVerify.ParseBoogieProgram(new List<string>(new string[] { "temp_out.bpl" }), false);
+
+ if (temp_program == null)
+ {
+ return false;
+ }
+
+ if (temp_program.Resolve() != 0)
+ {
+ return false;
+ }
+
+ if (temp_program.Typecheck() != 0)
+ {
+ return false;
+ }
+ return true;
+ }
+
+
+
+ public static Microsoft.Boogie.Type GetTypeOfIdX()
+ {
+ Contract.Requires(_X != null);
+ return _X.TypedIdent.Type;
+ }
+
+ public static Microsoft.Boogie.Type GetTypeOfIdY()
+ {
+ Contract.Requires(_Y != null);
+ return _Y.TypedIdent.Type;
+ }
+
+ public static Microsoft.Boogie.Type GetTypeOfIdZ()
+ {
+ Contract.Requires(_Z != null);
+ return _Z.TypedIdent.Type;
+ }
+
+ public static Microsoft.Boogie.Type GetTypeOfId(string dimension)
+ {
+ Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
+ if (dimension.Equals("X")) return GetTypeOfIdX();
+ if (dimension.Equals("Y")) return GetTypeOfIdY();
+ if (dimension.Equals("Z")) return GetTypeOfIdZ();
+ Debug.Assert(false);
+ return null;
+ }
+
+ public bool KernelHasIdX()
+ {
+ return _X != null;
+ }
+
+ public bool KernelHasIdY()
+ {
+ return _Y != null;
+ }
+
+ public bool KernelHasIdZ()
+ {
+ return _Z != null;
+ }
+
+ public bool KernelHasGroupIdX()
+ {
+ return _GROUP_X != null;
+ }
+
+ public bool KernelHasGroupIdY()
+ {
+ return _GROUP_Y != null;
+ }
+
+ public bool KernelHasGroupIdZ()
+ {
+ return _GROUP_Z != null;
+ }
+
+ public bool KernelHasNumGroupsX()
+ {
+ return _NUM_GROUPS_X != null;
+ }
+
+ public bool KernelHasNumGroupsY()
+ {
+ return _NUM_GROUPS_Y != null;
+ }
+
+ public bool KernelHasNumGroupsZ()
+ {
+ return _NUM_GROUPS_Z != null;
+ }
+
+ public bool KernelHasGroupSizeX()
+ {
+ return _GROUP_SIZE_X != null;
+ }
+
+ public bool KernelHasGroupSizeY()
+ {
+ return _GROUP_SIZE_Y != null;
+ }
+
+ public bool KernelHasGroupSizeZ()
+ {
+ return _GROUP_SIZE_Z != null;
+ }
+
+ internal static string StripThreadIdentifier(string p, out int id)
+ {
+ if (p.EndsWith("$1"))
+ {
+ id = 1;
+ return p.Substring(0, p.Length - 2);
+ }
+ if (p.EndsWith("$2"))
+ {
+ id = 2;
+ return p.Substring(0, p.Length - 2);
+ }
+
+ id = 0;
+ return p;
+ }
+
+ internal static string StripThreadIdentifier(string p)
+ {
+ int id;
+ return StripThreadIdentifier(p, out id);
+ }
+
+ private void GenerateStandardKernelContract()
+ {
+ RaceInstrumenter.AddKernelPrecondition();
+
+ IToken tok = KernelImplementation.tok;
+
+ GeneratePreconditionsForDimension(tok, "X");
+ GeneratePreconditionsForDimension(tok, "Y");
+ GeneratePreconditionsForDimension(tok, "Z");
+
+ RaceInstrumenter.AddStandardSourceVariablePreconditions();
+ RaceInstrumenter.AddStandardSourceVariablePostconditions();
+
+ foreach (Declaration D in Program.TopLevelDeclarations)
+ {
+ if (!(D is Procedure))
+ {
+ continue;
+ }
+ Procedure Proc = D as Procedure;
+ if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
+ {
+ continue;
+ }
+
+ Expr DistinctLocalIds =
+ Expr.Or(
+ Expr.Or(
+ Expr.Neq(
+ new IdentifierExpr(tok, MakeThreadId("X", 1)),
+ new IdentifierExpr(tok, MakeThreadId("X", 2))
+ ),
+ Expr.Neq(
+ new IdentifierExpr(tok, MakeThreadId("Y", 1)),
+ new IdentifierExpr(tok, MakeThreadId("Y", 2))
+ )
+ ),
+ Expr.Neq(
+ new IdentifierExpr(tok, MakeThreadId("Z", 1)),
+ new IdentifierExpr(tok, MakeThreadId("Z", 2))
+ )
+ );
+
+ Proc.Requires.Add(new Requires(false, Expr.Imp(ThreadsInSameGroup(), DistinctLocalIds)));
+
+ if (CommandLineOptions.OnlyIntraGroupRaceChecking)
+ {
+ Proc.Requires.Add(new Requires(false, ThreadsInSameGroup()));
+ }
+
+ if (Proc == KernelProcedure)
+ {
+ bool foundNonUniform = false;
+ int indexOfFirstNonUniformParameter;
+ for (indexOfFirstNonUniformParameter = 0; indexOfFirstNonUniformParameter < Proc.InParams.Length; indexOfFirstNonUniformParameter++)
+ {
+ if (!uniformityAnalyser.IsUniform(Proc.Name, StripThreadIdentifier(Proc.InParams[indexOfFirstNonUniformParameter].Name)))
+ {
+ foundNonUniform = true;
+ break;
+ }
+ }
+
+ if (foundNonUniform)
+ {
+ // I have a feeling this will never be reachable!!!
+ int numberOfNonUniformParameters = (Proc.InParams.Length - indexOfFirstNonUniformParameter) / 2;
+ for (int i = indexOfFirstNonUniformParameter; i < numberOfNonUniformParameters; i++)
+ {
+ Proc.Requires.Add(new Requires(false,
+ Expr.Eq(new IdentifierExpr(Proc.InParams[i].tok, Proc.InParams[i]),
+ new IdentifierExpr(Proc.InParams[i + numberOfNonUniformParameters].tok, Proc.InParams[i + numberOfNonUniformParameters]))));
+ }
+ }
+ }
+
+ }
+
+ foreach (Declaration D in Program.TopLevelDeclarations)
+ {
+ if (!(D is Implementation))
+ {
+ continue;
+ }
+ Implementation Impl = D as Implementation;
+
+ foreach (IRegion subregion in RootRegion(Impl).SubRegions())
+ {
+ RaceInstrumenter.AddSourceLocationLoopInvariants(Impl, subregion);
+ }
+ }
+
+ foreach (Declaration D in Program.TopLevelDeclarations)
+ {
+ if (!(D is Implementation))
+ {
+ continue;
+ }
+ Implementation Impl = D as Implementation;
+
+ if (QKeyValue.FindIntAttribute(Impl.Proc.Attributes, "inline", -1) == 1)
+ {
+ continue;
+ }
+ if (Impl.Proc == KernelProcedure)
+ {
+ continue;
+ }
+
+ new EnsureDisabledThreadHasNoEffectInstrumenter(this, Impl).instrument();
+
+ }
+
+ }
+
+ internal static Expr ThreadsInSameGroup()
+ {
+ return Expr.And(
+ Expr.And(
+ Expr.Eq(
+ new IdentifierExpr(Token.NoToken, MakeGroupId("X", 1)),
+ new IdentifierExpr(Token.NoToken, MakeGroupId("X", 2))
+ ),
+ Expr.Eq(
+ new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 1)),
+ new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 2))
+ )
+ ),
+ Expr.Eq(
+ new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 1)),
+ new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 2))
+ )
+ );
+ }
+
+ internal static void AddInvariantToAllLoops(Expr Invariant, StmtList stmtList)
+ {
+ foreach (BigBlock bb in stmtList.BigBlocks)
+ {
+ AddInvariantToAllLoops(Invariant, bb);
+ }
+ }
+
+ internal static void AddInvariantToAllLoops(Expr Invariant, BigBlock bb)
+ {
+ if (bb.ec is WhileCmd)
+ {
+ WhileCmd wc = bb.ec as WhileCmd;
+ wc.Invariants.Add(new AssertCmd(wc.tok, Invariant));
+ AddInvariantToAllLoops(Invariant, wc.Body);
+ }
+ Debug.Assert(!(bb.ec is IfCmd));
+ }
+
+ internal static int GetThreadSuffix(string p)
+ {
+ return Int32.Parse(p.Substring(p.IndexOf("$") + 1, p.Length - (p.IndexOf("$") + 1)));
+ }
+
+ private void GeneratePreconditionsForDimension(IToken tok, String dimension)
+ {
+ foreach (Declaration D in Program.TopLevelDeclarations.ToList())
+ {
+ if (!(D is Procedure))
+ {
+ continue;
+ }
+ Procedure Proc = D as Procedure;
+ if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
+ {
+ continue;
+ }
+
+ Expr GroupSizePositive;
+ Expr NumGroupsPositive;
+ Expr GroupIdNonNegative;
+ Expr GroupIdLessThanNumGroups;
+
+ if (GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)))
+ {
+ GroupSizePositive = MakeBVSgt(new IdentifierExpr(tok, GetGroupSize(dimension)), ZeroBV());
+ NumGroupsPositive = MakeBVSgt(new IdentifierExpr(tok, GetNumGroups(dimension)), ZeroBV());
+ GroupIdNonNegative = MakeBVSge(new IdentifierExpr(tok, GetGroupId(dimension)), ZeroBV());
+ GroupIdLessThanNumGroups = MakeBVSlt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)));
+ }
+ else
+ {
+ GroupSizePositive = Expr.Gt(new IdentifierExpr(tok, GetGroupSize(dimension)), Zero());
+ NumGroupsPositive = Expr.Gt(new IdentifierExpr(tok, GetNumGroups(dimension)), Zero());
+ GroupIdNonNegative = Expr.Ge(new IdentifierExpr(tok, GetGroupId(dimension)), Zero());
+ GroupIdLessThanNumGroups = Expr.Lt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)));
+ }
+
+ Proc.Requires.Add(new Requires(false, GroupSizePositive));
+ Proc.Requires.Add(new Requires(false, NumGroupsPositive));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdNonNegative)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdNonNegative)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdLessThanNumGroups)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdLessThanNumGroups)));
+
+ Expr ThreadIdNonNegative =
+ GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
+ MakeBVSge(new IdentifierExpr(tok, MakeThreadId(dimension)), ZeroBV())
+ :
+ Expr.Ge(new IdentifierExpr(tok, MakeThreadId(dimension)), Zero());
+ Expr ThreadIdLessThanGroupSize =
+ GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
+ MakeBVSlt(new IdentifierExpr(tok, MakeThreadId(dimension)), new IdentifierExpr(tok, GetGroupSize(dimension)))
+ :
+ Expr.Lt(new IdentifierExpr(tok, MakeThreadId(dimension)), new IdentifierExpr(tok, GetGroupSize(dimension)));
+
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdNonNegative)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdNonNegative)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdLessThanGroupSize)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdLessThanGroupSize)));
+
+ }
+
+ }
+
+ private Function GetOrCreateBVFunction(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Microsoft.Boogie.Type[] argTypes)
+ {
+ Function f = (Function)ResContext.LookUpProcedure(functionName);
+ if (f != null)
+ return f;
+
+ f = new Function(Token.NoToken, functionName,
+ new VariableSeq(argTypes.Select(t => new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "", t))).ToArray()),
+ new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "", resultType)));
+ f.AddAttribute("bvbuiltin", smtName);
+ Program.TopLevelDeclarations.Add(f);
+ ResContext.AddProcedure(f);
+ return f;
+ }
+
+ private Expr MakeBVFunctionCall(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Expr[] args)
+ {
+ Function f = GetOrCreateBVFunction(functionName, smtName, resultType, args.Select(a => a.Type).ToArray());
+ var e = new NAryExpr(Token.NoToken, new FunctionCall(f), new ExprSeq(args));
+ e.Type = resultType;
+ return e;
+ }
+
+ private Expr MakeBitVectorBinaryBoolean(string suffix, string smtName, Expr lhs, Expr rhs)
+ {
+ return MakeBVFunctionCall("BV" + lhs.Type.BvBits + "_" + suffix, smtName, Microsoft.Boogie.Type.Bool, lhs, rhs);
+ }
+
+ private Expr MakeBitVectorBinaryBitVector(string suffix, string smtName, Expr lhs, Expr rhs)
+ {
+ return MakeBVFunctionCall("BV" + lhs.Type.BvBits + "_" + suffix, smtName, lhs.Type, lhs, rhs);
+ }
+
+ internal Expr MakeBVSlt(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SLT", "bvslt", lhs, rhs); }
+ internal Expr MakeBVSgt(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SGT", "bvsgt", lhs, rhs); }
+ internal Expr MakeBVSge(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SGE", "bvsge", lhs, rhs); }
+
+ internal Expr MakeBVAnd(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("AND", "bvand", lhs, rhs); }
+ internal Expr MakeBVAdd(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("ADD", "bvadd", lhs, rhs); }
+ internal Expr MakeBVSub(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("SUB", "bvsub", lhs, rhs); }
+ internal Expr MakeBVMul(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("MUL", "bvmul", lhs, rhs); }
+ internal Expr MakeBVURem(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("UREM", "bvurem", lhs, rhs); }
+
+ internal static Expr MakeBitVectorBinaryBoolean(string functionName, Expr lhs, Expr rhs)
+ {
+ return new NAryExpr(lhs.tok, new FunctionCall(new Function(lhs.tok, functionName, new VariableSeq(new Variable[] {
+ new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg1", Microsoft.Boogie.Type.GetBvType(32))),
+ new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg2", Microsoft.Boogie.Type.GetBvType(32)))
+ }), new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "result", Microsoft.Boogie.Type.Bool)))), new ExprSeq(new Expr[] { lhs, rhs }));
+ }
+
+ internal static Expr MakeBitVectorBinaryBitVector(string functionName, Expr lhs, Expr rhs)
+ {
+ return new NAryExpr(lhs.tok, new FunctionCall(new Function(lhs.tok, functionName, new VariableSeq(new Variable[] {
+ new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg1", Microsoft.Boogie.Type.GetBvType(32))),
+ new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg2", Microsoft.Boogie.Type.GetBvType(32)))
+ }), new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "result", Microsoft.Boogie.Type.GetBvType(32))))), new ExprSeq(new Expr[] { lhs, rhs }));
+ }
+
+ private static bool IsBVFunctionCall(Expr e, string smtName, out ExprSeq args)
+ {
+ args = null;
+ var ne = e as NAryExpr;
+ if (ne == null)
+ return false;
+
+ var fc = ne.Fun as FunctionCall;
+ if (fc == null)
+ return false;
+
+ string bvBuiltin = QKeyValue.FindStringAttribute(fc.Func.Attributes, "bvbuiltin");
+ if (bvBuiltin == smtName)
+ {
+ args = ne.Args;
+ return true;
+ }
+
+ return false;
+ }
+
+ private static bool IsBVFunctionCall(Expr e, string smtName, out Expr lhs, out Expr rhs)
+ {
+ ExprSeq es;
+ if (IsBVFunctionCall(e, smtName, out es))
+ {
+ lhs = es[0]; rhs = es[1];
+ return true;
+ }
+ lhs = null; rhs = null;
+ return false;
+ }
+
+ internal static bool IsBVAdd(Expr e, out Expr lhs, out Expr rhs) { return IsBVFunctionCall(e, "bvadd", out lhs, out rhs); }
+ internal static bool IsBVMul(Expr e, out Expr lhs, out Expr rhs) { return IsBVFunctionCall(e, "bvmul", out lhs, out rhs); }
+
+ internal Constant GetGroupSize(string dimension)
+ {
+ Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
+ if (dimension.Equals("X")) return _GROUP_SIZE_X;
+ if (dimension.Equals("Y")) return _GROUP_SIZE_Y;
+ if (dimension.Equals("Z")) return _GROUP_SIZE_Z;
+ Debug.Assert(false);
+ return null;
+ }
+
+ internal Constant GetNumGroups(string dimension)
+ {
+ Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
+ if (dimension.Equals("X")) return _NUM_GROUPS_X;
+ if (dimension.Equals("Y")) return _NUM_GROUPS_Y;
+ if (dimension.Equals("Z")) return _NUM_GROUPS_Z;
+ Debug.Assert(false);
+ return null;
+ }
+
+ internal static Constant MakeThreadId(string dimension)
+ {
+ Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
+ string name = null;
+ if (dimension.Equals("X")) name = _X.Name;
+ if (dimension.Equals("Y")) name = _Y.Name;
+ if (dimension.Equals("Z")) name = _Z.Name;
+ Debug.Assert(name != null);
+ return new Constant(Token.NoToken, new TypedIdent(Token.NoToken, name, GetTypeOfId(dimension)));
+ }
+
+ internal static Constant MakeThreadId(string dimension, int number)
+ {
+ Constant resultWithoutThreadId = MakeThreadId(dimension);
+ return new Constant(Token.NoToken, new TypedIdent(
+ Token.NoToken, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension)));
+ }
+
+ internal static Constant GetGroupId(string dimension)
+ {
+ Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
+ if (dimension.Equals("X")) return _GROUP_X;
+ if (dimension.Equals("Y")) return _GROUP_Y;
+ if (dimension.Equals("Z")) return _GROUP_Z;
+ Debug.Assert(false);
+ return null;
+ }
+
+ internal static Constant MakeGroupId(string dimension, int number)
+ {
+ Constant resultWithoutThreadId = GetGroupId(dimension);
+ return new Constant(Token.NoToken, new TypedIdent(Token.NoToken, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension)));
+ }
+
+ private static LiteralExpr Zero()
+ {
+ return new LiteralExpr(Token.NoToken, BigNum.FromInt(0));
+ }
+
+ internal static LiteralExpr ZeroBV()
+ {
+ return new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 32);
+ }
+
+
+
+ private void GenerateBarrierImplementation()
+ {
+ IToken tok = BarrierProcedure.tok;
+
+ List<BigBlock> bigblocks = new List<BigBlock>();
+ BigBlock barrierEntryBlock = new BigBlock(tok, "__BarrierImpl", new CmdSeq(), null, null);
+ bigblocks.Add(barrierEntryBlock);
+
+ Debug.Assert((BarrierProcedure.InParams.Length % 2) == 0);
+ int paramsPerThread = BarrierProcedure.InParams.Length / 2;
+ IdentifierExpr P1 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[0].TypedIdent));
+ IdentifierExpr P2 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[paramsPerThread].TypedIdent));
+
+ Expr LocalFence1 = MakeFenceExpr(BarrierProcedure.InParams[1]);
+ Expr LocalFence2 = MakeFenceExpr(BarrierProcedure.InParams[paramsPerThread + 1]);
+
+ Expr GlobalFence1 = MakeFenceExpr(BarrierProcedure.InParams[2]);
+ Expr GlobalFence2 = MakeFenceExpr(BarrierProcedure.InParams[paramsPerThread + 2]);
+
+ Expr DivergenceCondition = Expr.Imp(ThreadsInSameGroup(), Expr.Eq(P1, P2));
+
+ Requires nonDivergenceRequires = new Requires(false, DivergenceCondition);
+ nonDivergenceRequires.Attributes = new QKeyValue(Token.NoToken, "barrier_divergence",
+ new List<object>(new object[] { }), null);
+ BarrierProcedure.Requires.Add(nonDivergenceRequires);
+
+ if (!CommandLineOptions.OnlyDivergence)
+ {
+ List<BigBlock> returnbigblocks = new List<BigBlock>();
+ returnbigblocks.Add(new BigBlock(tok, "__Disabled", new CmdSeq(), null, new ReturnCmd(tok)));
+ StmtList returnstatement = new StmtList(returnbigblocks, BarrierProcedure.tok);
+
+ Expr IfGuard = Expr.Or(Expr.And(Expr.Not(P1), Expr.Not(P2)), Expr.And(ThreadsInSameGroup(), Expr.Or(Expr.Not(P1), Expr.Not(P2))));
+ barrierEntryBlock.ec = new IfCmd(tok, IfGuard, returnstatement, null, null);
+ }
+
+ if(KernelArrayInfo.getGroupSharedArrays().Count > 0) {
+
+ bigblocks.AddRange(
+ MakeResetBlocks(Expr.And(P1, LocalFence1), KernelArrayInfo.getGroupSharedArrays()));
+
+ // This could be relaxed to take into account whether the threads are in different
+ // groups, but for now we keep it relatively simple
+
+ Expr AtLeastOneEnabledWithLocalFence =
+ Expr.Or(Expr.And(P1, LocalFence1), Expr.And(P2, LocalFence2));
+
+ if (SomeArrayModelledNonAdversarially(KernelArrayInfo.getGroupSharedArrays())) {
+ bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
+ new IfCmd(Token.NoToken,
+ AtLeastOneEnabledWithLocalFence,
+ new StmtList(MakeHavocBlocks(KernelArrayInfo.getGroupSharedArrays()), Token.NoToken), null, null), null));
+ }
+ }
+
+ if (KernelArrayInfo.getGlobalArrays().Count > 0)
+ {
+ Expr IfGuard1 = Expr.And(P1, GlobalFence1);
+ Expr IfGuard2 = Expr.And(P2, GlobalFence2);
+
+ bigblocks.AddRange(
+ MakeResetBlocks(Expr.And(P1, GlobalFence1), KernelArrayInfo.getGlobalArrays()));
+
+ Expr ThreadsInSameGroup_BothEnabled_AtLeastOneGlobalFence =
+ Expr.And(Expr.And(GPUVerifier.ThreadsInSameGroup(), Expr.And(P1, P2)), Expr.Or(GlobalFence1, GlobalFence2));
+
+ if (SomeArrayModelledNonAdversarially(KernelArrayInfo.getGlobalArrays())) {
+ bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
+ new IfCmd(Token.NoToken,
+ ThreadsInSameGroup_BothEnabled_AtLeastOneGlobalFence,
+ new StmtList(MakeHavocBlocks(KernelArrayInfo.getGlobalArrays()), Token.NoToken), null, null), null));
+ }
+ }
+
+ StmtList statements = new StmtList(bigblocks, BarrierProcedure.tok);
+ Implementation BarrierImplementation =
+ new Implementation(BarrierProcedure.tok, BarrierProcedure.Name, new TypeVariableSeq(),
+ BarrierProcedure.InParams, BarrierProcedure.OutParams, new VariableSeq(), statements);
+
+ if (CommandLineOptions.Unstructured)
+ BarrierImplementation.Resolve(ResContext);
+
+ BarrierImplementation.AddAttribute("inline", new object[] { new LiteralExpr(tok, BigNum.FromInt(1)) });
+ BarrierProcedure.AddAttribute("inline", new object[] { new LiteralExpr(tok, BigNum.FromInt(1)) });
+
+ BarrierImplementation.Proc = BarrierProcedure;
+
+ Program.TopLevelDeclarations.Add(BarrierImplementation);
+ }
+
+ private static NAryExpr MakeFenceExpr(Variable v) {
+ return Expr.Eq(new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, v.TypedIdent)),
+ new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 1));
+ }
+
+ private static Expr flagIsSet(Expr Flags, int flag)
+ {
+ return Expr.Eq(new BvExtractExpr(
+ Token.NoToken, Flags, flag, flag - 1),
+ new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 1));
+ }
+
+ private List<BigBlock> MakeResetBlocks(Expr ResetCondition, ICollection<Variable> variables)
+ {
+ Debug.Assert(variables.Count > 0);
+ List<BigBlock> result = new List<BigBlock>();
+ foreach (Variable v in variables)
+ {
+ result.Add(RaceInstrumenter.MakeResetReadWriteSetStatements(v, ResetCondition));
+ }
+ Debug.Assert(result.Count > 0);
+ return result;
+ }
+
+ private List<BigBlock> MakeHavocBlocks(ICollection<Variable> variables) {
+ Debug.Assert(variables.Count > 0);
+ List<BigBlock> result = new List<BigBlock>();
+ foreach (Variable v in variables) {
+ if (!ArrayModelledAdversarially(v)) {
+ result.Add(HavocSharedArray(v));
+ }
}
-
- return (lv.Length >= 2 && lv.Substring(0,2).Equals("_P")) ||
- (lv.Length > 3 && lv.Substring(0,3).Equals("_LC")) ||
- (lv.Length > 5 && lv.Substring(0,5).Equals("_temp"));
- }
-
-
-
-
- internal bool ProgramIsOK(Declaration d)
- {
- Debug.Assert(d is Procedure || d is Implementation);
- TokenTextWriter writer = new TokenTextWriter("temp_out.bpl");
- List<Declaration> RealDecls = Program.TopLevelDeclarations;
- List<Declaration> TempDecls = new List<Declaration>();
- foreach (Declaration d2 in RealDecls)
- {
- if (d is Procedure)
- {
- if ((d == d2) || !(d2 is Implementation || d2 is Procedure))
- {
- TempDecls.Add(d2);
- }
- }
- else if (d is Implementation)
- {
- if ((d == d2) || !(d2 is Implementation))
- {
- TempDecls.Add(d2);
- }
- }
- }
- Program.TopLevelDeclarations = TempDecls;
- Program.Emit(writer);
- writer.Close();
- Program.TopLevelDeclarations = RealDecls;
- Program temp_program = GPUVerify.ParseBoogieProgram(new List<string>(new string[] { "temp_out.bpl" }), false);
-
- if (temp_program == null)
- {
- return false;
- }
-
- if (temp_program.Resolve() != 0)
- {
- return false;
- }
-
- if (temp_program.Typecheck() != 0)
- {
- return false;
- }
- return true;
- }
-
-
-
- public Microsoft.Boogie.Type GetTypeOfIdX()
- {
- Contract.Requires(_X != null);
- return _X.TypedIdent.Type;
- }
-
- public Microsoft.Boogie.Type GetTypeOfIdY()
- {
- Contract.Requires(_Y != null);
- return _Y.TypedIdent.Type;
- }
-
- public Microsoft.Boogie.Type GetTypeOfIdZ()
- {
- Contract.Requires(_Z != null);
- return _Z.TypedIdent.Type;
- }
-
- public Microsoft.Boogie.Type GetTypeOfId(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return GetTypeOfIdX();
- if (dimension.Equals("Y")) return GetTypeOfIdY();
- if (dimension.Equals("Z")) return GetTypeOfIdZ();
- Debug.Assert(false);
- return null;
- }
-
- public bool KernelHasIdX()
- {
- return _X != null;
- }
-
- public bool KernelHasIdY()
- {
- return _Y != null;
- }
-
- public bool KernelHasIdZ()
- {
- return _Z != null;
- }
-
- public bool KernelHasGroupIdX()
- {
- return _GROUP_X != null;
- }
-
- public bool KernelHasGroupIdY()
- {
- return _GROUP_Y != null;
- }
-
- public bool KernelHasGroupIdZ()
- {
- return _GROUP_Z != null;
- }
-
- public bool KernelHasNumGroupsX()
- {
- return _NUM_GROUPS_X != null;
- }
-
- public bool KernelHasNumGroupsY()
- {
- return _NUM_GROUPS_Y != null;
- }
-
- public bool KernelHasNumGroupsZ()
- {
- return _NUM_GROUPS_Z != null;
- }
-
- public bool KernelHasGroupSizeX()
- {
- return _GROUP_SIZE_X != null;
- }
-
- public bool KernelHasGroupSizeY()
- {
- return _GROUP_SIZE_Y != null;
- }
-
- public bool KernelHasGroupSizeZ()
- {
- return _GROUP_SIZE_Z != null;
- }
-
- internal static string StripThreadIdentifier(string p, out int id)
- {
- if (p.EndsWith("$1"))
- {
- id = 1;
- return p.Substring(0, p.Length - 2);
- }
- if (p.EndsWith("$2"))
- {
- id = 2;
- return p.Substring(0, p.Length - 2);
- }
-
- id = 0;
- return p;
- }
-
- internal static string StripThreadIdentifier(string p)
- {
- int id;
- return StripThreadIdentifier(p, out id);
- }
-
- private void GenerateStandardKernelContract()
- {
- RaceInstrumenter.AddKernelPrecondition();
-
- IToken tok = KernelImplementation.tok;
-
- GeneratePreconditionsForDimension(tok, "X");
- GeneratePreconditionsForDimension(tok, "Y");
- GeneratePreconditionsForDimension(tok, "Z");
-
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (!(D is Procedure))
- {
- continue;
- }
- Procedure Proc = D as Procedure;
- if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
-
- Expr DistinctLocalIds =
- Expr.Or(
- Expr.Or(
- Expr.Neq(
- new IdentifierExpr(tok, MakeThreadId(tok, "X", 1)),
- new IdentifierExpr(tok, MakeThreadId(tok, "X", 2))
- ),
- Expr.Neq(
- new IdentifierExpr(tok, MakeThreadId(tok, "Y", 1)),
- new IdentifierExpr(tok, MakeThreadId(tok, "Y", 2))
- )
- ),
- Expr.Neq(
- new IdentifierExpr(tok, MakeThreadId(tok, "Z", 1)),
- new IdentifierExpr(tok, MakeThreadId(tok, "Z", 2))
- )
- );
-
- Proc.Requires.Add(new Requires(false, Expr.Imp(ThreadsInSameGroup(), DistinctLocalIds)));
-
- if (CommandLineOptions.OnlyIntraGroupRaceChecking)
- {
- Proc.Requires.Add(new Requires(false, ThreadsInSameGroup()));
- }
-
- if (Proc == KernelProcedure)
- {
- bool foundNonUniform = false;
- int indexOfFirstNonUniformParameter;
- for (indexOfFirstNonUniformParameter = 0; indexOfFirstNonUniformParameter < Proc.InParams.Length; indexOfFirstNonUniformParameter++)
- {
- if (!uniformityAnalyser.IsUniform(Proc.Name, StripThreadIdentifier(Proc.InParams[indexOfFirstNonUniformParameter].Name)))
- {
- foundNonUniform = true;
- break;
- }
- }
-
- if (foundNonUniform)
- {
- // I have a feeling this will never be reachable!!!
- int numberOfNonUniformParameters = (Proc.InParams.Length - indexOfFirstNonUniformParameter) / 2;
- for (int i = indexOfFirstNonUniformParameter; i < numberOfNonUniformParameters; i++)
- {
- Proc.Requires.Add(new Requires(false,
- Expr.Eq(new IdentifierExpr(Proc.InParams[i].tok, Proc.InParams[i]),
- new IdentifierExpr(Proc.InParams[i + numberOfNonUniformParameters].tok, Proc.InParams[i + numberOfNonUniformParameters]))));
- }
- }
- }
-
- }
-
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (!(D is Implementation))
- {
- continue;
- }
- Implementation Impl = D as Implementation;
-
- foreach (IRegion subregion in RootRegion(Impl).SubRegions())
- {
- RaceInstrumenter.AddSourceLocationLoopInvariants(Impl, subregion);
- }
- }
-
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (!(D is Implementation))
- {
- continue;
- }
- Implementation Impl = D as Implementation;
-
- if (QKeyValue.FindIntAttribute(Impl.Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
- if (Impl.Proc == KernelProcedure)
- {
- continue;
- }
-
- new EnsureDisabledThreadHasNoEffectInstrumenter(this, Impl).instrument();
-
- }
-
- }
-
- internal Expr ThreadsInSameGroup()
- {
- return Expr.And(
- Expr.And(
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, MakeGroupId("X", 1)),
- new IdentifierExpr(Token.NoToken, MakeGroupId("X", 2))
- ),
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 1)),
- new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 2))
- )
- ),
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 1)),
- new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 2))
- )
- );
- }
-
- internal static void AddInvariantToAllLoops(Expr Invariant, StmtList stmtList)
- {
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- AddInvariantToAllLoops(Invariant, bb);
- }
- }
-
- internal static void AddInvariantToAllLoops(Expr Invariant, BigBlock bb)
- {
- if (bb.ec is WhileCmd)
- {
- WhileCmd wc = bb.ec as WhileCmd;
- wc.Invariants.Add(new AssertCmd(wc.tok, Invariant));
- AddInvariantToAllLoops(Invariant, wc.Body);
- }
- Debug.Assert(!(bb.ec is IfCmd));
+ Debug.Assert(result.Count > 0);
+ return result;
}
- internal static int GetThreadSuffix(string p)
- {
- return Int32.Parse(p.Substring(p.IndexOf("$") + 1, p.Length - (p.IndexOf("$") + 1)));
- }
-
- private void GeneratePreconditionsForDimension(IToken tok, String dimension)
- {
- foreach (Declaration D in Program.TopLevelDeclarations.ToList())
- {
- if (!(D is Procedure))
- {
- continue;
- }
- Procedure Proc = D as Procedure;
- if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
-
- Expr GroupSizePositive;
- Expr NumGroupsPositive;
- Expr GroupIdNonNegative;
- Expr GroupIdLessThanNumGroups;
-
- if (GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)))
- {
- GroupSizePositive = MakeBVSgt(new IdentifierExpr(tok, GetGroupSize(dimension)), ZeroBV());
- NumGroupsPositive = MakeBVSgt(new IdentifierExpr(tok, GetNumGroups(dimension)), ZeroBV());
- GroupIdNonNegative = MakeBVSge(new IdentifierExpr(tok, GetGroupId(dimension)), ZeroBV());
- GroupIdLessThanNumGroups = MakeBVSlt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)));
- }
- else
- {
- GroupSizePositive = Expr.Gt(new IdentifierExpr(tok, GetGroupSize(dimension)), Zero());
- NumGroupsPositive = Expr.Gt(new IdentifierExpr(tok, GetNumGroups(dimension)), Zero());
- GroupIdNonNegative = Expr.Ge(new IdentifierExpr(tok, GetGroupId(dimension)), Zero());
- GroupIdLessThanNumGroups = Expr.Lt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)));
- }
-
- Proc.Requires.Add(new Requires(false, GroupSizePositive));
- Proc.Requires.Add(new Requires(false, NumGroupsPositive));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdNonNegative)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdNonNegative)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdLessThanNumGroups)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdLessThanNumGroups)));
-
- Expr ThreadIdNonNegative =
- GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
- MakeBVSge(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), ZeroBV())
- :
- Expr.Ge(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), Zero());
- Expr ThreadIdLessThanGroupSize =
- GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
- MakeBVSlt(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), new IdentifierExpr(tok, GetGroupSize(dimension)))
- :
- Expr.Lt(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), new IdentifierExpr(tok, GetGroupSize(dimension)));
-
- Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdNonNegative)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdNonNegative)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdLessThanGroupSize)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdLessThanGroupSize)));
-
- }
-
- }
-
- private Function GetOrCreateBVFunction(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Microsoft.Boogie.Type[] argTypes)
- {
- Function f = (Function)ResContext.LookUpProcedure(functionName);
- if (f != null)
- return f;
-
- f = new Function(Token.NoToken, functionName,
- new VariableSeq(argTypes.Select(t => new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "", t))).ToArray()),
- new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "", resultType)));
- f.AddAttribute("bvbuiltin", smtName);
- Program.TopLevelDeclarations.Add(f);
- ResContext.AddProcedure(f);
- return f;
- }
-
- private Expr MakeBVFunctionCall(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Expr[] args)
- {
- Function f = GetOrCreateBVFunction(functionName, smtName, resultType, args.Select(a => a.Type).ToArray());
- var e = new NAryExpr(Token.NoToken, new FunctionCall(f), new ExprSeq(args));
- e.Type = resultType;
- return e;
- }
-
- private Expr MakeBitVectorBinaryBoolean(string suffix, string smtName, Expr lhs, Expr rhs)
- {
- return MakeBVFunctionCall("BV" + lhs.Type.BvBits + "_" + suffix, smtName, Microsoft.Boogie.Type.Bool, lhs, rhs);
- }
-
- private Expr MakeBitVectorBinaryBitVector(string suffix, string smtName, Expr lhs, Expr rhs)
- {
- return MakeBVFunctionCall("BV" + lhs.Type.BvBits + "_" + suffix, smtName, lhs.Type, lhs, rhs);
- }
-
- internal Expr MakeBVSlt(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SLT", "bvslt", lhs, rhs); }
- internal Expr MakeBVSgt(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SGT", "bvsgt", lhs, rhs); }
- internal Expr MakeBVSge(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SGE", "bvsge", lhs, rhs); }
-
- internal Expr MakeBVAnd(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("AND", "bvand", lhs, rhs); }
- internal Expr MakeBVAdd(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("ADD", "bvadd", lhs, rhs); }
- internal Expr MakeBVSub(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("SUB", "bvsub", lhs, rhs); }
- internal Expr MakeBVMul(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("MUL", "bvmul", lhs, rhs); }
- internal Expr MakeBVURem(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("UREM", "bvurem", lhs, rhs); }
-
- internal static Expr MakeBitVectorBinaryBoolean(string functionName, Expr lhs, Expr rhs)
- {
- return new NAryExpr(lhs.tok, new FunctionCall(new Function(lhs.tok, functionName, new VariableSeq(new Variable[] {
- new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg1", Microsoft.Boogie.Type.GetBvType(32))),
- new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg2", Microsoft.Boogie.Type.GetBvType(32)))
- }), new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "result", Microsoft.Boogie.Type.Bool)))), new ExprSeq(new Expr[] { lhs, rhs }));
- }
-
- internal static Expr MakeBitVectorBinaryBitVector(string functionName, Expr lhs, Expr rhs)
- {
- return new NAryExpr(lhs.tok, new FunctionCall(new Function(lhs.tok, functionName, new VariableSeq(new Variable[] {
- new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg1", Microsoft.Boogie.Type.GetBvType(32))),
- new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg2", Microsoft.Boogie.Type.GetBvType(32)))
- }), new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "result", Microsoft.Boogie.Type.GetBvType(32))))), new ExprSeq(new Expr[] { lhs, rhs }));
- }
-
- private static bool IsBVFunctionCall(Expr e, string smtName, out ExprSeq args)
- {
- args = null;
- var ne = e as NAryExpr;
- if (ne == null)
- return false;
-
- var fc = ne.Fun as FunctionCall;
- if (fc == null)
- return false;
-
- string bvBuiltin = QKeyValue.FindStringAttribute(fc.Func.Attributes, "bvbuiltin");
- if (bvBuiltin == smtName)
- {
- args = ne.Args;
- return true;
- }
-
- return false;
- }
-
- private static bool IsBVFunctionCall(Expr e, string smtName, out Expr lhs, out Expr rhs)
- {
- ExprSeq es;
- if (IsBVFunctionCall(e, smtName, out es))
- {
- lhs = es[0]; rhs = es[1];
- return true;
- }
- lhs = null; rhs = null;
- return false;
- }
-
- internal static bool IsBVAdd(Expr e, out Expr lhs, out Expr rhs) { return IsBVFunctionCall(e, "bvadd", out lhs, out rhs); }
- internal static bool IsBVMul(Expr e, out Expr lhs, out Expr rhs) { return IsBVFunctionCall(e, "bvmul", out lhs, out rhs); }
-
- internal Constant GetGroupSize(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return _GROUP_SIZE_X;
- if (dimension.Equals("Y")) return _GROUP_SIZE_Y;
- if (dimension.Equals("Z")) return _GROUP_SIZE_Z;
- Debug.Assert(false);
- return null;
- }
-
- internal Constant GetNumGroups(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return _NUM_GROUPS_X;
- if (dimension.Equals("Y")) return _NUM_GROUPS_Y;
- if (dimension.Equals("Z")) return _NUM_GROUPS_Z;
- Debug.Assert(false);
- return null;
- }
-
- internal Constant MakeThreadId(IToken tok, string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- string name = null;
- if (dimension.Equals("X")) name = _X.Name;
- if (dimension.Equals("Y")) name = _Y.Name;
- if (dimension.Equals("Z")) name = _Z.Name;
- Debug.Assert(name != null);
- return new Constant(tok, new TypedIdent(tok, name, GetTypeOfId(dimension)));
- }
-
- internal Constant MakeThreadId(IToken tok, string dimension, int number)
- {
- Constant resultWithoutThreadId = MakeThreadId(tok, dimension);
- return new Constant(tok, new TypedIdent(tok, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension)));
- }
-
- internal Constant GetGroupId(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return _GROUP_X;
- if (dimension.Equals("Y")) return _GROUP_Y;
- if (dimension.Equals("Z")) return _GROUP_Z;
- Debug.Assert(false);
- return null;
- }
-
- internal Constant MakeGroupId(string dimension, int number)
- {
- Constant resultWithoutThreadId = GetGroupId(dimension);
- return new Constant(Token.NoToken, new TypedIdent(Token.NoToken, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension)));
- }
-
- private static LiteralExpr Zero()
- {
- return new LiteralExpr(Token.NoToken, BigNum.FromInt(0));
- }
-
- internal static LiteralExpr ZeroBV()
- {
- return new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 32);
- }
-
-
-
- private void GenerateBarrierImplementation()
- {
- IToken tok = BarrierProcedure.tok;
-
- List<BigBlock> bigblocks = new List<BigBlock>();
- BigBlock barrierEntryBlock = new BigBlock(tok, "__BarrierImpl", new CmdSeq(), null, null);
- bigblocks.Add(barrierEntryBlock);
-
- Debug.Assert((BarrierProcedure.InParams.Length % 2) == 0);
- int paramsPerThread = BarrierProcedure.InParams.Length / 2;
- IdentifierExpr P1 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[0].TypedIdent));
- IdentifierExpr P2 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[paramsPerThread].TypedIdent));
-
- Expr LocalFence1 = MakeFenceExpr(BarrierProcedure.InParams[1]);
- Expr LocalFence2 = MakeFenceExpr(BarrierProcedure.InParams[paramsPerThread + 1]);
-
- Expr GlobalFence1 = MakeFenceExpr(BarrierProcedure.InParams[2]);
- Expr GlobalFence2 = MakeFenceExpr(BarrierProcedure.InParams[paramsPerThread + 2]);
-
- Expr DivergenceCondition = Expr.Imp(ThreadsInSameGroup(), Expr.Eq(P1, P2));
-
- Requires nonDivergenceRequires = new Requires(false, DivergenceCondition);
- nonDivergenceRequires.Attributes = new QKeyValue(Token.NoToken, "barrier_divergence",
- new List<object>(new object[] { }), null);
- BarrierProcedure.Requires.Add(nonDivergenceRequires);
-
- if (!CommandLineOptions.OnlyDivergence)
- {
- List<BigBlock> returnbigblocks = new List<BigBlock>();
- returnbigblocks.Add(new BigBlock(tok, "__Disabled", new CmdSeq(), null, new ReturnCmd(tok)));
- StmtList returnstatement = new StmtList(returnbigblocks, BarrierProcedure.tok);
-
- Expr IfGuard = Expr.Or(Expr.And(Expr.Not(P1), Expr.Not(P2)), Expr.And(ThreadsInSameGroup(), Expr.Or(Expr.Not(P1), Expr.Not(P2))));
- barrierEntryBlock.ec = new IfCmd(tok, IfGuard, returnstatement, null, null);
- }
-
- if(KernelArrayInfo.getGroupSharedArrays().Count > 0) {
-
- Expr IfGuard1 = Expr.And(P1, LocalFence1);
- Expr IfGuard2 = Expr.And(P2, LocalFence2);
-
- bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
- new IfCmd(Token.NoToken, IfGuard1, new StmtList(MakeResetAndHavocBlocks(1, KernelArrayInfo.getGroupSharedArrays()), Token.NoToken), null, null),
- null));
- bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
- new IfCmd(Token.NoToken, IfGuard2, new StmtList(MakeResetAndHavocBlocks(2, KernelArrayInfo.getGroupSharedArrays()), Token.NoToken), null, null),
- null));
- }
-
- if (KernelArrayInfo.getGlobalArrays().Count > 0)
- {
- Expr IfGuard1 = Expr.And(P1, GlobalFence1);
- Expr IfGuard2 = Expr.And(P2, GlobalFence2);
-
- bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
- new IfCmd(Token.NoToken, IfGuard1, new StmtList(MakeResetAndHavocBlocks(1, KernelArrayInfo.getGlobalArrays()), Token.NoToken), null, null),
- null));
- bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
- new IfCmd(Token.NoToken, IfGuard2, new StmtList(MakeResetAndHavocBlocks(2, KernelArrayInfo.getGlobalArrays()), Token.NoToken), null, null),
- null));
- }
-
- foreach (Variable v in KernelArrayInfo.getAllNonLocalArrays())
- {
- if (!ArrayModelledAdversarially(v))
- {
- bigblocks.Add(AssumeEqualityBetweenSharedArrays(v, P1, P2, LocalFence1, LocalFence2, GlobalFence1, GlobalFence2));
- }
- }
-
- StmtList statements = new StmtList(bigblocks, BarrierProcedure.tok);
- Implementation BarrierImplementation =
- new Implementation(BarrierProcedure.tok, BarrierProcedure.Name, new TypeVariableSeq(),
- BarrierProcedure.InParams, BarrierProcedure.OutParams, new VariableSeq(), statements);
-
- if (CommandLineOptions.Unstructured)
- BarrierImplementation.Resolve(ResContext);
-
- BarrierImplementation.AddAttribute("inline", new object[] { new LiteralExpr(tok, BigNum.FromInt(1)) });
- BarrierProcedure.AddAttribute("inline", new object[] { new LiteralExpr(tok, BigNum.FromInt(1)) });
-
- BarrierImplementation.Proc = BarrierProcedure;
-
- Program.TopLevelDeclarations.Add(BarrierImplementation);
- }
-
- private static NAryExpr MakeFenceExpr(Variable v) {
- return Expr.Eq(new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, v.TypedIdent)),
- new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 1));
- }
-
- private static Expr flagIsSet(Expr Flags, int flag)
- {
- return Expr.Eq(new BvExtractExpr(
- Token.NoToken, Flags, flag, flag - 1),
- new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 1));
- }
-
- private List<BigBlock> MakeResetAndHavocBlocks(int Thread, ICollection<Variable> variables)
- {
- Debug.Assert(variables.Count > 0);
- List<BigBlock> ResetAndHavocBlocks = new List<BigBlock>();
- foreach (Variable v in variables)
- {
- ResetAndHavocBlocks.Add(RaceInstrumenter.MakeResetReadWriteSetStatements(v, Thread));
- if (!ArrayModelledAdversarially(v))
- {
- ResetAndHavocBlocks.Add(HavocSharedArray(v, Thread));
- }
- }
- Debug.Assert(ResetAndHavocBlocks.Count > 0);
- return ResetAndHavocBlocks;
- }
-
-
- public static bool HasZDimension(Variable v)
- {
- if (v.TypedIdent.Type is MapType)
- {
- MapType mt = v.TypedIdent.Type as MapType;
-
- if (mt.Result is MapType)
- {
- MapType mt2 = mt.Result as MapType;
- if (mt2.Result is MapType)
- {
- Debug.Assert(!((mt2.Result as MapType).Result is MapType));
- return true;
- }
- }
- }
- return false;
- }
-
- private BigBlock HavocSharedArray(Variable v, int thread)
- {
- IdentifierExpr vForThread = new IdentifierExpr(Token.NoToken, new VariableDualiser(thread, null, null).VisitVariable(v.Clone() as Variable));
- return new BigBlock(Token.NoToken, null, new CmdSeq(new Cmd[] { new HavocCmd(Token.NoToken, new IdentifierExprSeq(new IdentifierExpr[] { vForThread })) }), null, null);
- }
-
- private BigBlock AssumeEqualityBetweenSharedArrays(Variable v, Expr P1, Expr P2, Expr LocalFence1, Expr LocalFence2, Expr GlobalFence1, Expr GlobalFence2)
- {
- IdentifierExpr v1 = new IdentifierExpr(Token.NoToken, new VariableDualiser(1, null, null).VisitVariable(v.Clone() as Variable));
- IdentifierExpr v2 = new IdentifierExpr(Token.NoToken, new VariableDualiser(2, null, null).VisitVariable(v.Clone() as Variable));
-
- Expr AssumeGuard = Expr.Eq(v1, v2);
-
- Expr EqualityCondition = ThreadsInSameGroup();
-
- if (KernelArrayInfo.getGroupSharedArrays().Contains(v))
- {
- EqualityCondition = Expr.And(EqualityCondition,
- Expr.And(LocalFence1, LocalFence2));
- }
- else if (KernelArrayInfo.getGlobalArrays().Contains(v))
- {
- EqualityCondition = Expr.And(EqualityCondition,
- Expr.And(GlobalFence1, GlobalFence2));
- }
-
- AssumeGuard = Expr.Imp(EqualityCondition, AssumeGuard);
-
- return new BigBlock(Token.NoToken, null, new CmdSeq(new Cmd[] { new AssumeCmd(Token.NoToken, AssumeGuard) }), null, null);
- }
-
-
- internal static bool ModifiesSetContains(IdentifierExprSeq Modifies, IdentifierExpr v)
- {
- foreach (IdentifierExpr ie in Modifies)
- {
- if (ie.Name.Equals(v.Name))
- {
- return true;
- }
- }
- return false;
- }
-
- private void AbstractSharedState()
- {
- new AdversarialAbstraction(this).Abstract();
- }
-
- internal static string MakeOffsetVariableName(string Name, string AccessType)
- {
- return "_" + AccessType + "_OFFSET_" + Name;
- }
-
- internal static GlobalVariable MakeOffsetVariable(string Name, string ReadOrWrite)
- {
- return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeOffsetVariableName(Name, ReadOrWrite),
- Microsoft.Boogie.Type.GetBvType(32)));
- }
-
- internal static string MakeSourceVariableName(string Name, string AccessType)
- {
- return "_" + AccessType + "_SOURCE_" + Name;
- }
-
- internal static GlobalVariable MakeSourceVariable(string name, string ReadOrWrite)
- {
- return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeSourceVariableName(name, ReadOrWrite),
- Microsoft.Boogie.Type.GetBvType(32)));
- }
-
- internal GlobalVariable FindOrCreateAccessHasOccurredVariable(string varName, string accessType)
- {
- string name = MakeAccessHasOccurredVariableName(varName, accessType) + "$1";
- foreach(Declaration D in Program.TopLevelDeclarations)
- {
- if(D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name))
- {
- return D as GlobalVariable;
- }
- }
-
- GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
- MakeAccessHasOccurredVariable(varName, accessType)) as GlobalVariable;
-
- Program.TopLevelDeclarations.Add(result);
- return result;
-
- }
-
- internal GlobalVariable FindOrCreateOffsetVariable(string varName, string accessType)
- {
- string name = MakeOffsetVariableName(varName, accessType) + "$1";
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name))
- {
- return D as GlobalVariable;
- }
- }
-
- GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
- MakeOffsetVariable(varName, accessType)) as GlobalVariable;
-
- Program.TopLevelDeclarations.Add(result);
- return result;
-
- }
-
- internal GlobalVariable FindOrCreateSourceVariable(string varName, string accessType) {
- string name = MakeSourceVariableName(varName, accessType) + "$1";
- foreach (Declaration D in Program.TopLevelDeclarations) {
- if (D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name)) {
- return D as GlobalVariable;
+ private bool SomeArrayModelledNonAdversarially(ICollection<Variable> variables) {
+ Debug.Assert(variables.Count > 0);
+ foreach (Variable v in variables) {
+ if (!ArrayModelledAdversarially(v)) {
+ return true;
}
}
-
- GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
- MakeSourceVariable(varName, accessType)) as GlobalVariable;
-
- Program.TopLevelDeclarations.Add(result);
- return result;
-
- }
-
- internal static GlobalVariable MakeAccessHasOccurredVariable(string varName, string accessType)
- {
- return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeAccessHasOccurredVariableName(varName, accessType), Microsoft.Boogie.Type.Bool));
- }
-
- internal static string MakeAccessHasOccurredVariableName(string varName, string accessType)
- {
- return "_" + accessType + "_HAS_OCCURRED_" + varName;
- }
-
- internal static IdentifierExpr MakeAccessHasOccurredExpr(string varName, string accessType)
- {
- return new IdentifierExpr(Token.NoToken, MakeAccessHasOccurredVariable(varName, accessType));
- }
-
- internal static bool IsIntOrBv32(Microsoft.Boogie.Type type)
- {
- return type.Equals(Microsoft.Boogie.Type.Int) || type.Equals(Microsoft.Boogie.Type.GetBvType(32));
- }
-
- private void PullOutNonLocalAccesses()
- {
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Implementation)
- {
- (d as Implementation).StructuredStmts = PullOutNonLocalAccesses((d as Implementation).StructuredStmts, (d as Implementation));
- }
- }
- }
-
- private void RemoveElseIfs()
- {
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Implementation)
- {
- (d as Implementation).StructuredStmts = RemoveElseIfs((d as Implementation).StructuredStmts);
- }
- }
- }
-
- private void RemoveRedundantReturns()
- {
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Implementation)
- {
- RemoveRedundantReturns((d as Implementation).StructuredStmts);
- }
- }
- }
-
- private StmtList RemoveElseIfs(StmtList stmtList)
- {
- Contract.Requires(stmtList != null);
-
- StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
-
- foreach (BigBlock bodyBlock in stmtList.BigBlocks)
- {
- result.BigBlocks.Add(RemoveElseIfs(bodyBlock));
- }
-
- return result;
- }
-
- private void RemoveRedundantReturns(StmtList stmtList)
- {
- Contract.Requires(stmtList != null);
-
- BigBlock bb = stmtList.BigBlocks[stmtList.BigBlocks.Count - 1];
-
- if (bb.tc is ReturnCmd)
- {
- bb.tc = null;
- }
- }
-
- private BigBlock RemoveElseIfs(BigBlock bb)
- {
- BigBlock result = bb;
- if (bb.ec is IfCmd)
- {
- IfCmd IfCommand = bb.ec as IfCmd;
-
- Debug.Assert(IfCommand.elseIf == null || IfCommand.elseBlock == null);
-
- if (IfCommand.elseIf != null)
- {
- IfCommand.elseBlock = new StmtList(new List<BigBlock>(new BigBlock[] {
- new BigBlock(bb.tok, null, new CmdSeq(), IfCommand.elseIf, null)
- }), bb.tok);
- IfCommand.elseIf = null;
- }
-
- IfCommand.thn = RemoveElseIfs(IfCommand.thn);
- if (IfCommand.elseBlock != null)
- {
- IfCommand.elseBlock = RemoveElseIfs(IfCommand.elseBlock);
- }
-
- }
- else if (bb.ec is WhileCmd)
- {
- (bb.ec as WhileCmd).Body = RemoveElseIfs((bb.ec as WhileCmd).Body);
- }
-
- return result;
- }
-
- private StmtList PullOutNonLocalAccesses(StmtList stmtList, Implementation impl)
- {
- Contract.Requires(stmtList != null);
-
- StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
-
- foreach (BigBlock bodyBlock in stmtList.BigBlocks)
- {
- result.BigBlocks.Add(PullOutNonLocalAccesses(bodyBlock, impl));
- }
-
- return result;
- }
-
- private BigBlock PullOutNonLocalAccesses(BigBlock bb, Implementation impl)
- {
-
- BigBlock result = new BigBlock(bb.tok, bb.LabelName, new CmdSeq(), null, bb.tc);
-
- foreach (Cmd c in bb.simpleCmds)
- {
-
- if (c is CallCmd)
- {
+ return false;
+ }
+
+ public static bool HasZDimension(Variable v)
+ {
+ if (v.TypedIdent.Type is MapType)
+ {
+ MapType mt = v.TypedIdent.Type as MapType;
+
+ if (mt.Result is MapType)
+ {
+ MapType mt2 = mt.Result as MapType;
+ if (mt2.Result is MapType)
+ {
+ Debug.Assert(!((mt2.Result as MapType).Result is MapType));
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private BigBlock HavocSharedArray(Variable v)
+ {
+ return new BigBlock(Token.NoToken, null,
+ new CmdSeq(new Cmd[] { new HavocCmd(Token.NoToken,
+ new IdentifierExprSeq(new IdentifierExpr[] { new IdentifierExpr(Token.NoToken, v) })) }), null, null);
+ }
+
+ internal static bool ModifiesSetContains(IdentifierExprSeq Modifies, IdentifierExpr v)
+ {
+ foreach (IdentifierExpr ie in Modifies)
+ {
+ if (ie.Name.Equals(v.Name))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void AbstractSharedState()
+ {
+ new AdversarialAbstraction(this).Abstract();
+ }
+
+ internal static string MakeOffsetVariableName(string Name, string AccessType)
+ {
+ return "_" + AccessType + "_OFFSET_" + Name;
+ }
+
+ internal static GlobalVariable MakeOffsetVariable(string Name, string ReadOrWrite)
+ {
+ return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeOffsetVariableName(Name, ReadOrWrite),
+ Microsoft.Boogie.Type.GetBvType(32)));
+ }
+
+ internal static string MakeSourceVariableName(string Name, string AccessType)
+ {
+ return "_" + AccessType + "_SOURCE_" + Name;
+ }
+
+ internal static GlobalVariable MakeSourceVariable(string name, string ReadOrWrite)
+ {
+ return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeSourceVariableName(name, ReadOrWrite),
+ Microsoft.Boogie.Type.GetBvType(32)));
+ }
+
+ internal GlobalVariable FindOrCreateAccessHasOccurredVariable(string varName, string accessType)
+ {
+ string name = MakeAccessHasOccurredVariableName(varName, accessType) + "$1";
+ foreach(Declaration D in Program.TopLevelDeclarations)
+ {
+ if(D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name))
+ {
+ return D as GlobalVariable;
+ }
+ }
+
+ GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
+ MakeAccessHasOccurredVariable(varName, accessType)) as GlobalVariable;
+
+ Program.TopLevelDeclarations.Add(result);
+ return result;
+
+ }
+
+ internal GlobalVariable FindOrCreateOffsetVariable(string varName, string accessType)
+ {
+ string name = MakeOffsetVariableName(varName, accessType) + "$1";
+ foreach (Declaration D in Program.TopLevelDeclarations)
+ {
+ if (D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name))
+ {
+ return D as GlobalVariable;
+ }
+ }
+
+ GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
+ MakeOffsetVariable(varName, accessType)) as GlobalVariable;
+
+ Program.TopLevelDeclarations.Add(result);
+ return result;
+
+ }
+
+ internal GlobalVariable FindOrCreateSourceVariable(string varName, string accessType) {
+ string name = MakeSourceVariableName(varName, accessType) + "$1";
+ foreach (Declaration D in Program.TopLevelDeclarations) {
+ if (D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name)) {
+ return D as GlobalVariable;
+ }
+ }
+
+ GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
+ MakeSourceVariable(varName, accessType)) as GlobalVariable;
+
+ Program.TopLevelDeclarations.Add(result);
+ return result;
+
+ }
+
+ internal static GlobalVariable MakeAccessHasOccurredVariable(string varName, string accessType)
+ {
+ return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeAccessHasOccurredVariableName(varName, accessType), Microsoft.Boogie.Type.Bool));
+ }
+
+ internal static string MakeAccessHasOccurredVariableName(string varName, string accessType)
+ {
+ return "_" + accessType + "_HAS_OCCURRED_" + varName;
+ }
+
+ internal static IdentifierExpr MakeAccessHasOccurredExpr(string varName, string accessType)
+ {
+ return new IdentifierExpr(Token.NoToken, MakeAccessHasOccurredVariable(varName, accessType));
+ }
+
+ internal static bool IsIntOrBv32(Microsoft.Boogie.Type type)
+ {
+ return type.Equals(Microsoft.Boogie.Type.Int) || type.Equals(Microsoft.Boogie.Type.GetBvType(32));
+ }
+
+ private void PullOutNonLocalAccesses()
+ {
+ foreach (Declaration d in Program.TopLevelDeclarations)
+ {
+ if (d is Implementation)
+ {
+ (d as Implementation).StructuredStmts = PullOutNonLocalAccesses((d as Implementation).StructuredStmts, (d as Implementation));
+ }
+ }
+ }
+
+ private void RemoveElseIfs()
+ {
+ foreach (Declaration d in Program.TopLevelDeclarations)
+ {
+ if (d is Implementation)
+ {
+ (d as Implementation).StructuredStmts = RemoveElseIfs((d as Implementation).StructuredStmts);
+ }
+ }
+ }
+
+ private void RemoveRedundantReturns()
+ {
+ foreach (Declaration d in Program.TopLevelDeclarations)
+ {
+ if (d is Implementation)
+ {
+ RemoveRedundantReturns((d as Implementation).StructuredStmts);
+ }
+ }
+ }
+
+ private StmtList RemoveElseIfs(StmtList stmtList)
+ {
+ Contract.Requires(stmtList != null);
+
+ StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
+
+ foreach (BigBlock bodyBlock in stmtList.BigBlocks)
+ {
+ result.BigBlocks.Add(RemoveElseIfs(bodyBlock));
+ }
+
+ return result;
+ }
+
+ private void RemoveRedundantReturns(StmtList stmtList)
+ {
+ Contract.Requires(stmtList != null);
+
+ BigBlock bb = stmtList.BigBlocks[stmtList.BigBlocks.Count - 1];
+
+ if (bb.tc is ReturnCmd)
+ {
+ bb.tc = null;
+ }
+ }
+
+ private BigBlock RemoveElseIfs(BigBlock bb)
+ {
+ BigBlock result = bb;
+ if (bb.ec is IfCmd)
+ {
+ IfCmd IfCommand = bb.ec as IfCmd;
+
+ Debug.Assert(IfCommand.elseIf == null || IfCommand.elseBlock == null);
+
+ if (IfCommand.elseIf != null)
+ {
+ IfCommand.elseBlock = new StmtList(new List<BigBlock>(new BigBlock[] {
+ new BigBlock(bb.tok, null, new CmdSeq(), IfCommand.elseIf, null)
+ }), bb.tok);
+ IfCommand.elseIf = null;
+ }
+
+ IfCommand.thn = RemoveElseIfs(IfCommand.thn);
+ if (IfCommand.elseBlock != null)
+ {
+ IfCommand.elseBlock = RemoveElseIfs(IfCommand.elseBlock);
+ }
+
+ }
+ else if (bb.ec is WhileCmd)
+ {
+ (bb.ec as WhileCmd).Body = RemoveElseIfs((bb.ec as WhileCmd).Body);
+ }
+
+ return result;
+ }
+
+ private StmtList PullOutNonLocalAccesses(StmtList stmtList, Implementation impl)
+ {
+ Contract.Requires(stmtList != null);
+
+ StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
+
+ foreach (BigBlock bodyBlock in stmtList.BigBlocks)
+ {
+ result.BigBlocks.Add(PullOutNonLocalAccesses(bodyBlock, impl));
+ }
+
+ return result;
+ }
+
+ private BigBlock PullOutNonLocalAccesses(BigBlock bb, Implementation impl)
+ {
+
+ BigBlock result = new BigBlock(bb.tok, bb.LabelName, new CmdSeq(), null, bb.tc);
+
+ foreach (Cmd c in bb.simpleCmds)
+ {
+
+ if (c is CallCmd)
+ {
CallCmd call = c as CallCmd;
- List<Expr> newIns = new List<Expr>();
-
- for (int i = 0; i < call.Ins.Count; i++)
- {
- Expr e = call.Ins[i];
-
- while (NonLocalAccessCollector.ContainsNonLocalAccess(e, KernelArrayInfo))
- {
- AssignCmd assignToTemp;
- LocalVariable tempDecl;
- e = ExtractLocalAccessToTemp(e, out assignToTemp, out tempDecl);
- result.simpleCmds.Add(assignToTemp);
- impl.LocVars.Add(tempDecl);
- }
-
- newIns.Add(e);
-
- }
-
- CallCmd newCall = new CallCmd(call.tok, call.callee, newIns, call.Outs);
- newCall.Proc = call.Proc;
- result.simpleCmds.Add(newCall);
- }
- else if (c is AssignCmd)
- {
- AssignCmd assign = c as AssignCmd;
-
- if (assign.Lhss.Zip(assign.Rhss, (lhs, rhs) =>
- !NonLocalAccessCollector.ContainsNonLocalAccess(rhs, KernelArrayInfo) ||
- (!NonLocalAccessCollector.ContainsNonLocalAccess(lhs, KernelArrayInfo) &&
- NonLocalAccessCollector.IsNonLocalAccess(rhs, KernelArrayInfo))).All(b => b))
- {
- result.simpleCmds.Add(c);
- }
- else
- {
- Debug.Assert(assign.Lhss.Count == 1 && assign.Rhss.Count == 1);
- AssignLhs lhs = assign.Lhss.ElementAt(0);
- Expr rhs = assign.Rhss.ElementAt(0);
- rhs = PullOutNonLocalAccessesIntoTemps(result, rhs, impl);
- List<AssignLhs> newLhss = new List<AssignLhs>();
- newLhss.Add(lhs);
- List<Expr> newRhss = new List<Expr>();
- newRhss.Add(rhs);
- result.simpleCmds.Add(new AssignCmd(assign.tok, newLhss, newRhss));
- }
-
- }
- else if (c is HavocCmd)
- {
- result.simpleCmds.Add(c);
- }
- else if (c is AssertCmd)
- {
- result.simpleCmds.Add(new AssertCmd(c.tok, PullOutNonLocalAccessesIntoTemps(result, (c as AssertCmd).Expr, impl)));
- }
- else if (c is AssumeCmd)
- {
- result.simpleCmds.Add(new AssumeCmd(c.tok, PullOutNonLocalAccessesIntoTemps(result, (c as AssumeCmd).Expr, impl)));
- }
- else
- {
- Console.WriteLine(c);
- Debug.Assert(false);
- }
- }
-
- if (bb.ec is WhileCmd)
- {
- WhileCmd WhileCommand = bb.ec as WhileCmd;
- while (NonLocalAccessCollector.ContainsNonLocalAccess(WhileCommand.Guard, KernelArrayInfo))
- {
- AssignCmd assignToTemp;
- LocalVariable tempDecl;
- WhileCommand.Guard = ExtractLocalAccessToTemp(WhileCommand.Guard, out assignToTemp, out tempDecl);
- result.simpleCmds.Add(assignToTemp);
- impl.LocVars.Add(tempDecl);
- }
- result.ec = new WhileCmd(WhileCommand.tok, WhileCommand.Guard, WhileCommand.Invariants, PullOutNonLocalAccesses(WhileCommand.Body, impl));
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd IfCommand = bb.ec as IfCmd;
- Debug.Assert(IfCommand.elseIf == null); // "else if" must have been eliminated by this phase
- while (NonLocalAccessCollector.ContainsNonLocalAccess(IfCommand.Guard, KernelArrayInfo))
- {
- AssignCmd assignToTemp;
- LocalVariable tempDecl;
- IfCommand.Guard = ExtractLocalAccessToTemp(IfCommand.Guard, out assignToTemp, out tempDecl);
- result.simpleCmds.Add(assignToTemp);
- impl.LocVars.Add(tempDecl);
- }
- result.ec = new IfCmd(IfCommand.tok, IfCommand.Guard, PullOutNonLocalAccesses(IfCommand.thn, impl), IfCommand.elseIf, IfCommand.elseBlock != null ? PullOutNonLocalAccesses(IfCommand.elseBlock, impl) : null);
- }
- else if (bb.ec is BreakCmd)
- {
- result.ec = bb.ec;
- }
- else
- {
- Debug.Assert(bb.ec == null);
- }
-
- return result;
-
- }
-
- private Expr PullOutNonLocalAccessesIntoTemps(BigBlock result, Expr e, Implementation impl)
- {
- while (NonLocalAccessCollector.ContainsNonLocalAccess(e, KernelArrayInfo))
- {
- AssignCmd assignToTemp;
- LocalVariable tempDecl;
- e = ExtractLocalAccessToTemp(e, out assignToTemp, out tempDecl);
- result.simpleCmds.Add(assignToTemp);
- impl.LocVars.Add(tempDecl);
- }
- return e;
- }
-
- private Expr ExtractLocalAccessToTemp(Expr rhs, out AssignCmd tempAssignment, out LocalVariable tempDeclaration)
- {
- NonLocalAccessExtractor extractor = new NonLocalAccessExtractor(TempCounter, KernelArrayInfo);
- TempCounter++;
- rhs = extractor.VisitExpr(rhs);
- tempAssignment = extractor.Assignment;
- tempDeclaration = extractor.Declaration;
- return rhs;
- }
-
- private void MakeKernelDualised()
- {
-
- List<Declaration> NewTopLevelDeclarations = new List<Declaration>();
-
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Procedure)
- {
-
- new KernelDualiser(this).DualiseProcedure(d as Procedure);
-
- NewTopLevelDeclarations.Add(d as Procedure);
-
- continue;
-
- }
-
- if (d is Implementation)
- {
-
- new KernelDualiser(this).DualiseImplementation(d as Implementation, CommandLineOptions.Unstructured);
-
- NewTopLevelDeclarations.Add(d as Implementation);
-
- continue;
-
- }
-
- if (d is Variable && ((d as Variable).IsMutable || IsThreadLocalIdConstant(d as Variable)
- || IsGroupIdConstant(d as Variable) ))
- {
- NewTopLevelDeclarations.Add(new VariableDualiser(1, null, null).VisitVariable((Variable)d.Clone()));
- if (!QKeyValue.FindBoolAttribute(d.Attributes, "race_checking"))
- {
- NewTopLevelDeclarations.Add(new VariableDualiser(2, null, null).VisitVariable((Variable)d.Clone()));
- }
-
- continue;
- }
-
- NewTopLevelDeclarations.Add(d);
-
- }
-
- Program.TopLevelDeclarations = NewTopLevelDeclarations;
-
- }
-
- private void MakeKernelPredicated()
- {
- if (CommandLineOptions.Unstructured)
- {
- if (CommandLineOptions.SmartPredication)
- {
- SmartBlockPredicator.Predicate(Program);
- }
- else
- {
- BlockPredicator.Predicate(Program, /*createCandidateInvariants=*/CommandLineOptions.Inference);
- }
- return;
- }
-
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Procedure)
- {
- Procedure proc = d as Procedure;
- IdentifierExpr enabled = new IdentifierExpr(proc.tok,
- new LocalVariable(proc.tok, new TypedIdent(proc.tok, "_P", Microsoft.Boogie.Type.Bool)));
- Expr predicateExpr;
- if (!uniformityAnalyser.IsUniform(proc.Name))
- {
- // Add predicate to start of parameter list
- VariableSeq NewIns = new VariableSeq();
- NewIns.Add(enabled.Decl);
- foreach (Variable v in proc.InParams)
- {
- NewIns.Add(v);
- }
- proc.InParams = NewIns;
- predicateExpr = enabled;
- }
- else
- {
- predicateExpr = Expr.True;
- }
-
- RequiresSeq newRequires = new RequiresSeq();
- foreach (Requires r in proc.Requires)
- {
- newRequires.Add(new Requires(r.Free, Predicator.ProcessEnabledIntrinsics(r.Condition, predicateExpr)));
- }
- proc.Requires = newRequires;
-
- EnsuresSeq newEnsures = new EnsuresSeq();
- foreach (Ensures e in proc.Ensures)
- {
- newEnsures.Add(new Ensures(e.Free, Predicator.ProcessEnabledIntrinsics(e.Condition, predicateExpr)));
- }
- proc.Ensures = newEnsures;
-
- }
- else if (d is Implementation)
- {
- Implementation impl = d as Implementation;
- new Predicator(this, !uniformityAnalyser.IsUniform(impl.Name)).transform
- (impl);
- }
- }
-
- }
-
- private void CheckKernelParameters()
- {
- if (KernelProcedure.OutParams.Length != 0)
- {
- Error(KernelProcedure.tok, "Kernel should not take return anything");
- }
- }
-
-
- private int Check()
- {
+ if (QKeyValue.FindBoolAttribute(call.Proc.Attributes, "barrier_invariant") ||
+ QKeyValue.FindBoolAttribute(call.Proc.Attributes, "binary_barrier_invariant")) {
+ // Do not pull non-local accesses out of barrier invariants
+ continue;
+ }
+
+ List<Expr> newIns = new List<Expr>();
+
+ for (int i = 0; i < call.Ins.Count; i++)
+ {
+ Expr e = call.Ins[i];
+
+ while (NonLocalAccessCollector.ContainsNonLocalAccess(e, KernelArrayInfo))
+ {
+ AssignCmd assignToTemp;
+ LocalVariable tempDecl;
+ e = ExtractLocalAccessToTemp(e, out assignToTemp, out tempDecl);
+ result.simpleCmds.Add(assignToTemp);
+ impl.LocVars.Add(tempDecl);
+ }
+
+ newIns.Add(e);
+
+ }
+
+ CallCmd newCall = new CallCmd(call.tok, call.callee, newIns, call.Outs);
+ newCall.Proc = call.Proc;
+ result.simpleCmds.Add(newCall);
+ }
+ else if (c is AssignCmd)
+ {
+ AssignCmd assign = c as AssignCmd;
+
+ if (assign.Lhss.Zip(assign.Rhss, (lhs, rhs) =>
+ !NonLocalAccessCollector.ContainsNonLocalAccess(rhs, KernelArrayInfo) ||
+ (!NonLocalAccessCollector.ContainsNonLocalAccess(lhs, KernelArrayInfo) &&
+ NonLocalAccessCollector.IsNonLocalAccess(rhs, KernelArrayInfo))).All(b => b))
+ {
+ result.simpleCmds.Add(c);
+ }
+ else
+ {
+ Debug.Assert(assign.Lhss.Count == 1 && assign.Rhss.Count == 1);
+ AssignLhs lhs = assign.Lhss.ElementAt(0);
+ Expr rhs = assign.Rhss.ElementAt(0);
+ rhs = PullOutNonLocalAccessesIntoTemps(result, rhs, impl);
+ List<AssignLhs> newLhss = new List<AssignLhs>();
+ newLhss.Add(lhs);
+ List<Expr> newRhss = new List<Expr>();
+ newRhss.Add(rhs);
+ result.simpleCmds.Add(new AssignCmd(assign.tok, newLhss, newRhss));
+ }
+
+ }
+ else if (c is HavocCmd)
+ {
+ result.simpleCmds.Add(c);
+ }
+ else if (c is AssertCmd)
+ {
+ // Do not pull non-local accesses out of assert commands
+ continue;
+ }
+ else if (c is AssumeCmd)
+ {
+ result.simpleCmds.Add(new AssumeCmd(c.tok, PullOutNonLocalAccessesIntoTemps(result, (c as AssumeCmd).Expr, impl)));
+ }
+ else
+ {
+ Console.WriteLine(c);
+ Debug.Assert(false);
+ }
+ }
+
+ if (bb.ec is WhileCmd)
+ {
+ WhileCmd WhileCommand = bb.ec as WhileCmd;
+ while (NonLocalAccessCollector.ContainsNonLocalAccess(WhileCommand.Guard, KernelArrayInfo))
+ {
+ AssignCmd assignToTemp;
+ LocalVariable tempDecl;
+ WhileCommand.Guard = ExtractLocalAccessToTemp(WhileCommand.Guard, out assignToTemp, out tempDecl);
+ result.simpleCmds.Add(assignToTemp);
+ impl.LocVars.Add(tempDecl);
+ }
+ result.ec = new WhileCmd(WhileCommand.tok, WhileCommand.Guard, WhileCommand.Invariants, PullOutNonLocalAccesses(WhileCommand.Body, impl));
+ }
+ else if (bb.ec is IfCmd)
+ {
+ IfCmd IfCommand = bb.ec as IfCmd;
+ Debug.Assert(IfCommand.elseIf == null); // "else if" must have been eliminated by this phase
+ while (NonLocalAccessCollector.ContainsNonLocalAccess(IfCommand.Guard, KernelArrayInfo))
+ {
+ AssignCmd assignToTemp;
+ LocalVariable tempDecl;
+ IfCommand.Guard = ExtractLocalAccessToTemp(IfCommand.Guard, out assignToTemp, out tempDecl);
+ result.simpleCmds.Add(assignToTemp);
+ impl.LocVars.Add(tempDecl);
+ }
+ result.ec = new IfCmd(IfCommand.tok, IfCommand.Guard, PullOutNonLocalAccesses(IfCommand.thn, impl), IfCommand.elseIf, IfCommand.elseBlock != null ? PullOutNonLocalAccesses(IfCommand.elseBlock, impl) : null);
+ }
+ else if (bb.ec is BreakCmd)
+ {
+ result.ec = bb.ec;
+ }
+ else
+ {
+ Debug.Assert(bb.ec == null);
+ }
+
+ return result;
+
+ }
+
+ private Expr PullOutNonLocalAccessesIntoTemps(BigBlock result, Expr e, Implementation impl)
+ {
+ while (NonLocalAccessCollector.ContainsNonLocalAccess(e, KernelArrayInfo))
+ {
+ AssignCmd assignToTemp;
+ LocalVariable tempDecl;
+ e = ExtractLocalAccessToTemp(e, out assignToTemp, out tempDecl);
+ result.simpleCmds.Add(assignToTemp);
+ impl.LocVars.Add(tempDecl);
+ }
+ return e;
+ }
+
+ private Expr ExtractLocalAccessToTemp(Expr rhs, out AssignCmd tempAssignment, out LocalVariable tempDeclaration)
+ {
+ NonLocalAccessExtractor extractor = new NonLocalAccessExtractor(TempCounter, KernelArrayInfo);
+ TempCounter++;
+ rhs = extractor.VisitExpr(rhs);
+ tempAssignment = extractor.Assignment;
+ tempDeclaration = extractor.Declaration;
+ return rhs;
+ }
+
+ private void MakeKernelDualised()
+ {
+
+ List<Declaration> NewTopLevelDeclarations = new List<Declaration>();
+
+ for(int i = 0; i < Program.TopLevelDeclarations.Count; i++)
+ {
+ Declaration d = Program.TopLevelDeclarations[i];
+
+ if (d is Procedure)
+ {
+
+ new KernelDualiser(this).DualiseProcedure(d as Procedure);
+
+ NewTopLevelDeclarations.Add(d as Procedure);
+
+ continue;
+
+ }
+
+ if (d is Implementation)
+ {
+
+ new KernelDualiser(this).DualiseImplementation(d as Implementation, CommandLineOptions.Unstructured);
+
+ NewTopLevelDeclarations.Add(d as Implementation);
+
+ continue;
+
+ }
+
+ if (d is Variable && ((d as Variable).IsMutable ||
+ IsThreadLocalIdConstant(d as Variable) ||
+ IsGroupIdConstant(d as Variable))) {
+ var v = d as Variable;
+
+ if (KernelArrayInfo.getGlobalArrays().Contains(v)) {
+ NewTopLevelDeclarations.Add(v);
+ continue;
+ }
+
+ if (KernelArrayInfo.getGroupSharedArrays().Contains(v)) {
+ Variable newV = new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken,
+ v.Name, new MapType(Token.NoToken, new TypeVariableSeq(),
+ new TypeSeq(new Microsoft.Boogie.Type[] { Microsoft.Boogie.Type.Bool }),
+ v.TypedIdent.Type)));
+ newV.Attributes = v.Attributes;
+ NewTopLevelDeclarations.Add(newV);
+ continue;
+ }
+
+ NewTopLevelDeclarations.Add(new VariableDualiser(1, null, null).VisitVariable((Variable)v.Clone()));
+ if (!QKeyValue.FindBoolAttribute(v.Attributes, "race_checking")) {
+ NewTopLevelDeclarations.Add(new VariableDualiser(2, null, null).VisitVariable((Variable)v.Clone()));
+ }
+
+ continue;
+ }
+
+ NewTopLevelDeclarations.Add(d);
+
+ }
+
+ Program.TopLevelDeclarations = NewTopLevelDeclarations;
+
+ }
+
+ private void MakeKernelPredicated()
+ {
+ if (CommandLineOptions.Unstructured)
+ {
+ if (CommandLineOptions.SmartPredication)
+ {
+ SmartBlockPredicator.Predicate(Program, proc => true, uniformityAnalyser);
+ }
+ else
+ {
+ BlockPredicator.Predicate(Program, /*createCandidateInvariants=*/CommandLineOptions.Inference);
+ }
+ return;
+ }
+
+ foreach (Declaration d in Program.TopLevelDeclarations)
+ {
+ if (d is Procedure)
+ {
+ Procedure proc = d as Procedure;
+ IdentifierExpr enabled = new IdentifierExpr(proc.tok,
+ new LocalVariable(proc.tok, new TypedIdent(proc.tok, "_P", Microsoft.Boogie.Type.Bool)));
+ Expr predicateExpr;
+ if (!uniformityAnalyser.IsUniform(proc.Name))
+ {
+ // Add predicate to start of parameter list
+ VariableSeq NewIns = new VariableSeq();
+ NewIns.Add(enabled.Decl);
+ foreach (Variable v in proc.InParams)
+ {
+ NewIns.Add(v);
+ }
+ proc.InParams = NewIns;
+ predicateExpr = enabled;
+ }
+ else
+ {
+ predicateExpr = Expr.True;
+ }
+
+ RequiresSeq newRequires = new RequiresSeq();
+ foreach (Requires r in proc.Requires)
+ {
+ newRequires.Add(new Requires(r.Free, Predicator.ProcessEnabledIntrinsics(r.Condition, predicateExpr)));
+ }
+ proc.Requires = newRequires;
+
+ EnsuresSeq newEnsures = new EnsuresSeq();
+ foreach (Ensures e in proc.Ensures)
+ {
+ newEnsures.Add(new Ensures(e.Free, Predicator.ProcessEnabledIntrinsics(e.Condition, predicateExpr)));
+ }
+ proc.Ensures = newEnsures;
+
+ }
+ else if (d is Implementation)
+ {
+ Implementation impl = d as Implementation;
+ new Predicator(this, !uniformityAnalyser.IsUniform(impl.Name)).transform
+ (impl);
+ }
+ }
+
+ }
+
+ private void CheckKernelParameters()
+ {
+ if (KernelProcedure.OutParams.Length != 0)
+ {
+ Error(KernelProcedure.tok, "Kernel should not take return anything");
+ }
+ }
+
+
+ private int Check()
+ {
BarrierProcedure = FindOrCreateBarrierProcedure();
- KernelProcedure = CheckExactlyOneKernelProcedure();
-
- if (ErrorCount > 0)
- {
- return ErrorCount;
- }
-
- if (BarrierProcedure.InParams.Length != 2)
- {
- Error(BarrierProcedure, "Barrier procedure must take exactly two arguments");
- }
- else if (!BarrierProcedure.InParams[0].TypedIdent.Type.Equals(new BvType(1)))
- {
- Error(BarrierProcedure, "First argument to barrier procedure must have type bv1");
- }
- else if (!BarrierProcedure.InParams[1].TypedIdent.Type.Equals(new BvType(1))) {
- Error(BarrierProcedure, "Second argument to barrier procedure must have type bv1");
- }
-
- if (BarrierProcedure.OutParams.Length != 0)
- {
- Error(BarrierProcedure, "Barrier procedure must not return any results");
- }
-
- if (!FindNonLocalVariables())
- {
- return ErrorCount;
- }
-
- CheckKernelImplementation();
- return ErrorCount;
- }
-
- public static bool IsThreadLocalIdConstant(Variable variable)
- {
- return variable.Name.Equals(_X.Name) || variable.Name.Equals(_Y.Name) || variable.Name.Equals(_Z.Name);
- }
-
- public static bool IsGroupIdConstant(Variable variable)
- {
- return variable.Name.Equals(_GROUP_X.Name) || variable.Name.Equals(_GROUP_Y.Name) || variable.Name.Equals(_GROUP_Z.Name);
- }
-
- internal void AddCandidateInvariant(IRegion region, Expr e, string tag)
- {
- region.AddInvariant(Program.CreateCandidateInvariant(e, tag));
- }
-
- internal Implementation GetImplementation(string procedureName)
- {
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (D is Implementation && ((D as Implementation).Name == procedureName))
- {
- return D as Implementation;
- }
- }
- Debug.Assert(false);
- return null;
- }
-
-
- internal bool ContainsBarrierCall(IRegion loop)
- {
- foreach (Cmd c in loop.Cmds())
- {
- if (c is CallCmd && ((c as CallCmd).Proc == BarrierProcedure))
- {
- return true;
- }
- }
-
- return false;
- }
-
-
-
- internal bool ArrayModelledAdversarially(Variable v)
- {
- if (CommandLineOptions.AdversarialAbstraction)
- {
- return true;
- }
- if (CommandLineOptions.EqualityAbstraction)
- {
- return false;
- }
- return !arrayControlFlowAnalyser.MayAffectControlFlow(v.Name);
- }
-
- internal Expr GlobalIdExpr(string dimension)
- {
- return MakeBVAdd(MakeBVMul(
- new IdentifierExpr(Token.NoToken, GetGroupId(dimension)), new IdentifierExpr(Token.NoToken, GetGroupSize(dimension))),
- new IdentifierExpr(Token.NoToken, MakeThreadId(Token.NoToken, dimension)));
- }
-
- internal IRegion RootRegion(Implementation Impl)
- {
- if (CommandLineOptions.Unstructured)
- return new UnstructuredRegion(Program, Impl);
- else
- return new StructuredRegion(Impl);
- }
-
-
- public static bool IsGivenConstant(Expr e, Constant c)
- {
- if (!(e is IdentifierExpr))
- return false;
-
- var varName = ((IdentifierExpr)e).Decl.Name;
- return (StripThreadIdentifier(varName) == StripThreadIdentifier(c.Name));
- }
-
- public bool SubstIsGivenConstant(Implementation impl, Expr e, Constant c)
- {
- if (!(e is IdentifierExpr))
- return false;
- e = varDefAnalyses[impl].SubstDefinitions(e, impl.Name);
- return IsGivenConstant(e, c);
- }
-
- public Constant GetLocalIdConst(int dim)
- {
- switch (dim)
- {
- case 0: return _X;
- case 1: return _Y;
- case 2: return _Z;
- default: Debug.Assert(false);
- return null;
- }
- }
-
- public Constant GetGroupIdConst(int dim)
- {
- switch (dim)
- {
- case 0: return _GROUP_X;
- case 1: return _GROUP_Y;
- case 2: return _GROUP_Z;
- default: Debug.Assert(false);
- return null;
- }
- }
-
- public Constant GetGroupSizeConst(int dim)
- {
- switch (dim)
- {
- case 0: return _GROUP_SIZE_X;
- case 1: return _GROUP_SIZE_Y;
- case 2: return _GROUP_SIZE_Z;
- default: Debug.Assert(false);
- return null;
- }
- }
-
- public bool IsLocalId(Expr e, int dim, Implementation impl)
- {
- return SubstIsGivenConstant(impl, e, GetLocalIdConst(dim));
- }
-
- public bool IsGlobalId(Expr e, int dim, Implementation impl)
- {
- e = varDefAnalyses[impl].SubstDefinitions(e, impl.Name);
-
- if (e is NAryExpr && (e as NAryExpr).Fun.FunctionName.Equals("BV32_ADD"))
- {
- NAryExpr nary = e as NAryExpr;
- Constant localId = GetLocalIdConst(dim);
-
- if (IsGivenConstant(nary.Args[1], localId))
- {
- return IsGroupIdTimesGroupSize(nary.Args[0], dim);
- }
-
- if (IsGivenConstant(nary.Args[0], localId))
- {
- return IsGroupIdTimesGroupSize(nary.Args[1], dim);
- }
- }
-
- return false;
- }
-
- private bool IsGroupIdTimesGroupSize(Expr expr, int dim)
- {
- if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("BV32_MUL"))
- {
- NAryExpr innerNary = expr as NAryExpr;
-
- if (IsGroupIdAndSize(dim, innerNary.Args[0], innerNary.Args[1]))
- {
- return true;
- }
-
- if (IsGroupIdAndSize(dim, innerNary.Args[1], innerNary.Args[0]))
- {
- return true;
- }
- }
- return false;
- }
-
- private bool IsGroupIdAndSize(int dim, Expr maybeGroupId, Expr maybeGroupSize)
- {
- return IsGivenConstant(maybeGroupId, GetGroupIdConst(dim)) &&
- IsGivenConstant(maybeGroupSize, GetGroupSizeConst(dim));
- }
-
- internal Expr MaybeDualise(Expr e, int id, string procName)
- {
- if (id == 0)
- return e;
- else
- return (Expr)new VariableDualiser(id, uniformityAnalyser, procName).Visit(e.Clone());
- }
-
- internal static bool IsConstantInCurrentRegion(IdentifierExpr expr) {
- return (expr.Decl is Constant) ||
- (expr.Decl is Formal && ((Formal)expr.Decl).InComing);
- }
-
- }
-
-
-}
+ KernelProcedure = CheckExactlyOneKernelProcedure();
+
+ if (ErrorCount > 0)
+ {
+ return ErrorCount;
+ }
+
+ if (BarrierProcedure.InParams.Length != 2)
+ {
+ Error(BarrierProcedure, "Barrier procedure must take exactly two arguments");
+ }
+ else if (!BarrierProcedure.InParams[0].TypedIdent.Type.Equals(new BvType(1)))
+ {
+ Error(BarrierProcedure, "First argument to barrier procedure must have type bv1");
+ }
+ else if (!BarrierProcedure.InParams[1].TypedIdent.Type.Equals(new BvType(1))) {
+ Error(BarrierProcedure, "Second argument to barrier procedure must have type bv1");
+ }
+
+ if (BarrierProcedure.OutParams.Length != 0)
+ {
+ Error(BarrierProcedure, "Barrier procedure must not return any results");
+ }
+
+ if (!FindNonLocalVariables())
+ {
+ return ErrorCount;
+ }
+
+ CheckKernelImplementation();
+ return ErrorCount;
+ }
+
+ public static bool IsThreadLocalIdConstant(Variable variable)
+ {
+ return variable.Name.Equals(_X.Name) || variable.Name.Equals(_Y.Name) || variable.Name.Equals(_Z.Name);
+ }
+
+ public static bool IsGroupIdConstant(Variable variable)
+ {
+ return variable.Name.Equals(_GROUP_X.Name) || variable.Name.Equals(_GROUP_Y.Name) || variable.Name.Equals(_GROUP_Z.Name);
+ }
+
+ internal void AddCandidateInvariant(IRegion region, Expr e, string tag)
+ {
+ region.AddInvariant(Program.CreateCandidateInvariant(e, tag));
+ }
+
+ internal Implementation GetImplementation(string procedureName)
+ {
+ foreach (Declaration D in Program.TopLevelDeclarations)
+ {
+ if (D is Implementation && ((D as Implementation).Name == procedureName))
+ {
+ return D as Implementation;
+ }
+ }
+ Error(Token.NoToken, "No implementation found for procedure \"" + procedureName + "\"");
+ Environment.Exit(1);
+ return null;
+ }
+
+
+ internal bool ContainsBarrierCall(IRegion loop)
+ {
+ foreach (Cmd c in loop.Cmds())
+ {
+ if (c is CallCmd && ((c as CallCmd).Proc == BarrierProcedure))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+
+ internal bool ArrayModelledAdversarially(Variable v)
+ {
+ if (CommandLineOptions.AdversarialAbstraction)
+ {
+ return true;
+ }
+ if (CommandLineOptions.EqualityAbstraction)
+ {
+ return false;
+ }
+ return !arrayControlFlowAnalyser.MayAffectControlFlow(v.Name);
+ }
+
+ internal Expr GlobalIdExpr(string dimension)
+ {
+ return MakeBVAdd(MakeBVMul(
+ new IdentifierExpr(Token.NoToken, GetGroupId(dimension)), new IdentifierExpr(Token.NoToken, GetGroupSize(dimension))),
+ new IdentifierExpr(Token.NoToken, MakeThreadId(dimension)));
+ }
+
+ internal IRegion RootRegion(Implementation Impl)
+ {
+ if (CommandLineOptions.Unstructured)
+ return new UnstructuredRegion(Program, Impl);
+ else
+ return new StructuredRegion(Impl);
+ }
+
+
+ public static bool IsGivenConstant(Expr e, Constant c)
+ {
+ if (!(e is IdentifierExpr))
+ return false;
+
+ var varName = ((IdentifierExpr)e).Decl.Name;
+ return (StripThreadIdentifier(varName) == StripThreadIdentifier(c.Name));
+ }
+
+ public bool SubstIsGivenConstant(Implementation impl, Expr e, Constant c)
+ {
+ if (!(e is IdentifierExpr))
+ return false;
+ e = varDefAnalyses[impl].SubstDefinitions(e, impl.Name);
+ return IsGivenConstant(e, c);
+ }
+
+ public Constant GetLocalIdConst(int dim)
+ {
+ switch (dim)
+ {
+ case 0: return _X;
+ case 1: return _Y;
+ case 2: return _Z;
+ default: Debug.Assert(false);
+ return null;
+ }
+ }
+
+ public Constant GetGroupIdConst(int dim)
+ {
+ switch (dim)
+ {
+ case 0: return _GROUP_X;
+ case 1: return _GROUP_Y;
+ case 2: return _GROUP_Z;
+ default: Debug.Assert(false);
+ return null;
+ }
+ }
+
+ public Constant GetGroupSizeConst(int dim)
+ {
+ switch (dim)
+ {
+ case 0: return _GROUP_SIZE_X;
+ case 1: return _GROUP_SIZE_Y;
+ case 2: return _GROUP_SIZE_Z;
+ default: Debug.Assert(false);
+ return null;
+ }
+ }
+
+ public bool IsLocalId(Expr e, int dim, Implementation impl)
+ {
+ return SubstIsGivenConstant(impl, e, GetLocalIdConst(dim));
+ }
+
+ public bool IsGlobalId(Expr e, int dim, Implementation impl)
+ {
+ e = varDefAnalyses[impl].SubstDefinitions(e, impl.Name);
+
+ if (e is NAryExpr && (e as NAryExpr).Fun.FunctionName.Equals("BV32_ADD"))
+ {
+ NAryExpr nary = e as NAryExpr;
+ Constant localId = GetLocalIdConst(dim);
+
+ if (IsGivenConstant(nary.Args[1], localId))
+ {
+ return IsGroupIdTimesGroupSize(nary.Args[0], dim);
+ }
+
+ if (IsGivenConstant(nary.Args[0], localId))
+ {
+ return IsGroupIdTimesGroupSize(nary.Args[1], dim);
+ }
+ }
+
+ return false;
+ }
+
+ private bool IsGroupIdTimesGroupSize(Expr expr, int dim)
+ {
+ if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("BV32_MUL"))
+ {
+ NAryExpr innerNary = expr as NAryExpr;
+
+ if (IsGroupIdAndSize(dim, innerNary.Args[0], innerNary.Args[1]))
+ {
+ return true;
+ }
+
+ if (IsGroupIdAndSize(dim, innerNary.Args[1], innerNary.Args[0]))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool IsGroupIdAndSize(int dim, Expr maybeGroupId, Expr maybeGroupSize)
+ {
+ return IsGivenConstant(maybeGroupId, GetGroupIdConst(dim)) &&
+ IsGivenConstant(maybeGroupSize, GetGroupSizeConst(dim));
+ }
+
+ internal Expr MaybeDualise(Expr e, int id, string procName)
+ {
+ if (id == 0)
+ return e;
+ else
+ return (Expr)new VariableDualiser(id, uniformityAnalyser, procName).Visit(e.Clone());
+ }
+
+ internal static bool IsConstantInCurrentRegion(IdentifierExpr expr) {
+ return (expr.Decl is Constant) ||
+ (expr.Decl is Formal && ((Formal)expr.Decl).InComing);
+ }
+
+ internal static Expr GroupSharedIndexingExpr(int Thread) {
+ return Thread == 1 ? Expr.True : ThreadsInSameGroup();
+ }
+
+ }
+
+
+}
diff --git a/Source/GPUVerify/GPUVerify.csproj b/Source/GPUVerify/GPUVerify.csproj
index 08913944..2bcc5b15 100644
--- a/Source/GPUVerify/GPUVerify.csproj
+++ b/Source/GPUVerify/GPUVerify.csproj
@@ -108,8 +108,11 @@
<Compile Include="AdversarialAbstraction.cs" />
<Compile Include="ArrayControlFlowAnalyser.cs" />
<Compile Include="AsymmetricExpressionFinder.cs" />
+ <Compile Include="BarrierInvariantDescriptor.cs" />
+ <Compile Include="BinaryBarrierInvariantDescriptor.cs" />
<Compile Include="StrideConstraint.cs" />
<Compile Include="ReducedStrengthAnalysis.cs" />
+ <Compile Include="UnaryBarrierInvariantDescriptor.cs" />
<Compile Include="UnstructuredRegion.cs" />
<Compile Include="IRegion.cs" />
<Compile Include="InvariantGenerationRules\LoopVariableBoundsInvariantGenerator.cs" />
@@ -135,8 +138,6 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RaceInstrumenter.cs" />
<Compile Include="ReadCollector.cs" />
- <Compile Include="UniformExpressionAnalysisVisitor.cs" />
- <Compile Include="UniformityAnalyser.cs" />
<Compile Include="VariableDualiser.cs" />
<Compile Include="VariablesOccurringInExpressionVisitor.cs" />
<Compile Include="VariableDefinitionAnalysis.cs" />
@@ -170,11 +171,11 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
-->
</Project> \ No newline at end of file
diff --git a/Source/GPUVerify/IRaceInstrumenter.cs b/Source/GPUVerify/IRaceInstrumenter.cs
index 13349650..7f14fcd0 100644
--- a/Source/GPUVerify/IRaceInstrumenter.cs
+++ b/Source/GPUVerify/IRaceInstrumenter.cs
@@ -1,27 +1,31 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-
-namespace GPUVerify
-{
- interface IRaceInstrumenter
- {
- void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region);
- void AddKernelPrecondition();
-
- void AddRaceCheckingInstrumentation();
-
- void AddRaceCheckingDeclarations();
-
- BigBlock MakeResetReadWriteSetStatements(Variable v, int thread);
-
- void AddRaceCheckingCandidateRequires(Procedure Proc);
-
- void AddRaceCheckingCandidateEnsures(Procedure Proc);
-
- void AddSourceLocationLoopInvariants(Implementation impl, IRegion region);
-
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+
+namespace GPUVerify
+{
+ interface IRaceInstrumenter
+ {
+ void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region);
+ void AddKernelPrecondition();
+
+ void AddRaceCheckingInstrumentation();
+
+ void AddRaceCheckingDeclarations();
+
+ BigBlock MakeResetReadWriteSetStatements(Variable v, Expr ResetCondition);
+
+ void AddRaceCheckingCandidateRequires(Procedure Proc);
+
+ void AddRaceCheckingCandidateEnsures(Procedure Proc);
+
+ void AddSourceLocationLoopInvariants(Implementation impl, IRegion region);
+
+ void DoHoudiniPointerAnalysis(Procedure Proc);
+ void AddStandardSourceVariablePreconditions();
+
+ void AddStandardSourceVariablePostconditions();
+ }
+}
diff --git a/Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs b/Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs
index f73bddb6..c21261b0 100644
--- a/Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs
+++ b/Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs
@@ -1,54 +1,55 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-
-namespace GPUVerify.InvariantGenerationRules
-{
- class LoopVariableBoundsInvariantGenerator : InvariantGenerationRule
- {
-
- public LoopVariableBoundsInvariantGenerator(GPUVerifier verifier)
- : base(verifier)
- {
-
- }
-
- public override void GenerateCandidates(Implementation Impl, IRegion region)
- {
- if (verifier.uniformityAnalyser.IsUniform(Impl.Name, region.Guard()))
- {
- VariablesOccurringInExpressionVisitor visitor = new VariablesOccurringInExpressionVisitor();
- visitor.VisitExpr(region.Guard());
- foreach (Variable v in visitor.GetVariables())
- {
- if (!verifier.ContainsNamedVariable(LoopInvariantGenerator.GetModifiedVariables(region), v.Name))
- {
- continue;
- }
-
- if (IsBVType (v.TypedIdent.Type))
- {
- int BVWidth = (v.TypedIdent.Type as BvType).Bits;
-
- verifier.AddCandidateInvariant(region,
- verifier.MakeBVSge(
- new IdentifierExpr(v.tok, v),
- new LiteralExpr(v.tok, BigNum.FromInt(0), BVWidth)), "loop guard variable non-negative");
- }
- }
- }
- }
-
- private bool IsBVType(Microsoft.Boogie.Type type)
- {
- return type.Equals(Microsoft.Boogie.Type.GetBvType(32))
- || type.Equals(Microsoft.Boogie.Type.GetBvType(16))
- || type.Equals(Microsoft.Boogie.Type.GetBvType(8));
- }
-
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics;
+using Microsoft.Boogie;
+using Microsoft.Basetypes;
+
+namespace GPUVerify.InvariantGenerationRules
+{
+ class LoopVariableBoundsInvariantGenerator : InvariantGenerationRule
+ {
+
+ public LoopVariableBoundsInvariantGenerator(GPUVerifier verifier)
+ : base(verifier)
+ {
+
+ }
+
+ public override void GenerateCandidates(Implementation Impl, IRegion region)
+ {
+ var guard = region.Guard();
+ if (guard != null && verifier.uniformityAnalyser.IsUniform(Impl.Name, guard))
+ {
+ var visitor = new VariablesOccurringInExpressionVisitor();
+ visitor.VisitExpr(guard);
+ foreach (Variable v in visitor.GetVariables())
+ {
+ if (!verifier.ContainsNamedVariable(LoopInvariantGenerator.GetModifiedVariables(region), v.Name))
+ {
+ continue;
+ }
+
+ if (IsBVType (v.TypedIdent.Type))
+ {
+ int BVWidth = (v.TypedIdent.Type as BvType).Bits;
+
+ verifier.AddCandidateInvariant(region,
+ verifier.MakeBVSge(
+ new IdentifierExpr(v.tok, v),
+ new LiteralExpr(v.tok, BigNum.FromInt(0), BVWidth)), "loop guard variable non-negative");
+ }
+ }
+ }
+ }
+
+ private bool IsBVType(Microsoft.Boogie.Type type)
+ {
+ return type.Equals(Microsoft.Boogie.Type.GetBvType(32))
+ || type.Equals(Microsoft.Boogie.Type.GetBvType(16))
+ || type.Equals(Microsoft.Boogie.Type.GetBvType(8));
+ }
+
+ }
+}
diff --git a/Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs b/Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs
index 8b24bb0a..8dab8474 100644
--- a/Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs
+++ b/Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs
@@ -1,61 +1,61 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-
-namespace GPUVerify.InvariantGenerationRules
-{
- class PowerOfTwoInvariantGenerator : InvariantGenerationRule
- {
-
- public PowerOfTwoInvariantGenerator(GPUVerifier verifier)
- : base(verifier)
- {
-
- }
-
- public override void GenerateCandidates(Implementation Impl, IRegion region)
- {
- foreach (Variable v in Impl.LocVars)
- {
- string basicName = GPUVerifier.StripThreadIdentifier(v.Name);
- if (verifier.uniformityAnalyser.IsUniform(Impl.Name, basicName))
- {
- if (verifier.mayBePowerOfTwoAnalyser.MayBePowerOfTwo(Impl.Name, basicName))
- {
- if (verifier.ContainsNamedVariable(LoopInvariantGenerator.GetModifiedVariables(region), basicName))
- {
- verifier.AddCandidateInvariant(region, MakePowerOfTwoExpr(v), "pow2 disjunction");
- for (int i = (1 << 15); i > 0; i >>= 1)
- {
- verifier.AddCandidateInvariant(region,
- GPUVerifier.MakeBitVectorBinaryBoolean("BV32_LT",
- new IdentifierExpr(v.tok, v),
- new LiteralExpr(v.tok, BigNum.FromInt(i), 32)), "pow2 less than " + i);
- }
- verifier.AddCandidateInvariant(region,
- Expr.Neq(new IdentifierExpr(v.tok, v),
- new LiteralExpr(v.tok, BigNum.FromInt(0), 32)), "pow2 not zero");
- }
- }
- }
- }
- }
-
- private Expr MakePowerOfTwoExpr(Variable v)
- {
- Expr result = null;
- for (int i = 1 << 15; i > 0; i >>= 1)
- {
- Expr eq = Expr.Eq(new IdentifierExpr(v.tok, v), new LiteralExpr(v.tok, BigNum.FromInt(i), 32));
- result = (result == null ? eq : Expr.Or(eq, result));
- }
-
- return Expr.Or(Expr.Eq(new IdentifierExpr(v.tok, v), new LiteralExpr(v.tok, BigNum.FromInt(0), 32)), result);
- }
-
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics;
+using Microsoft.Boogie;
+using Microsoft.Basetypes;
+
+namespace GPUVerify.InvariantGenerationRules
+{
+ class PowerOfTwoInvariantGenerator : InvariantGenerationRule
+ {
+
+ public PowerOfTwoInvariantGenerator(GPUVerifier verifier)
+ : base(verifier)
+ {
+
+ }
+
+ public override void GenerateCandidates(Implementation Impl, IRegion region)
+ {
+ foreach (Variable v in Impl.LocVars)
+ {
+ string basicName = GPUVerifier.StripThreadIdentifier(v.Name);
+ if (verifier.uniformityAnalyser.IsUniform(Impl.Name, basicName))
+ {
+ if (verifier.mayBePowerOfTwoAnalyser.MayBePowerOfTwo(Impl.Name, basicName))
+ {
+ if (verifier.ContainsNamedVariable(LoopInvariantGenerator.GetModifiedVariables(region), basicName))
+ {
+ verifier.AddCandidateInvariant(region, MakePowerOfTwoExpr(v), "pow2 disjunction");
+ for (int i = (1 << 15); i > 0; i >>= 1)
+ {
+ verifier.AddCandidateInvariant(region,
+ verifier.MakeBVSlt(
+ new IdentifierExpr(v.tok, v),
+ new LiteralExpr(v.tok, BigNum.FromInt(i), 32)), "pow2 less than " + i);
+ }
+ verifier.AddCandidateInvariant(region,
+ Expr.Neq(new IdentifierExpr(v.tok, v),
+ new LiteralExpr(v.tok, BigNum.FromInt(0), 32)), "pow2 not zero");
+ }
+ }
+ }
+ }
+ }
+
+ private Expr MakePowerOfTwoExpr(Variable v)
+ {
+ Expr result = null;
+ for (int i = 1 << 15; i > 0; i >>= 1)
+ {
+ Expr eq = Expr.Eq(new IdentifierExpr(v.tok, v), new LiteralExpr(v.tok, BigNum.FromInt(i), 32));
+ result = (result == null ? eq : Expr.Or(eq, result));
+ }
+
+ return Expr.Or(Expr.Eq(new IdentifierExpr(v.tok, v), new LiteralExpr(v.tok, BigNum.FromInt(0), 32)), result);
+ }
+
+ }
+}
diff --git a/Source/GPUVerify/KernelDualiser.cs b/Source/GPUVerify/KernelDualiser.cs
index 272d0a1b..3a2a1776 100644
--- a/Source/GPUVerify/KernelDualiser.cs
+++ b/Source/GPUVerify/KernelDualiser.cs
@@ -9,10 +9,13 @@ using Microsoft.Basetypes;
namespace GPUVerify {
class KernelDualiser {
- private GPUVerifier verifier;
+ internal GPUVerifier verifier;
+
+ private List<BarrierInvariantDescriptor> BarrierInvariantDescriptors;
public KernelDualiser(GPUVerifier verifier) {
this.verifier = verifier;
+ BarrierInvariantDescriptors = new List<BarrierInvariantDescriptor>();
}
private string procName = null;
@@ -74,7 +77,7 @@ namespace GPUVerify {
return result;
}
- private QKeyValue MakeThreadSpecificAttributes(QKeyValue attributes, int Thread) {
+ internal QKeyValue MakeThreadSpecificAttributes(QKeyValue attributes, int Thread) {
if (attributes == null) {
return null;
}
@@ -100,6 +103,45 @@ namespace GPUVerify {
if (c is CallCmd) {
CallCmd Call = c as CallCmd;
+ if (QKeyValue.FindBoolAttribute(Call.Proc.Attributes, "barrier_invariant")) {
+ // There should be a predicate, an invariant expression, and at least one instantiation
+ Debug.Assert(Call.Ins.Count >= 3);
+ var BIDescriptor = new UnaryBarrierInvariantDescriptor(Call.Ins[0],
+ Expr.Neq(Call.Ins[1],
+ new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 1)),
+ Call.Attributes,
+ this, procName);
+ for (var i = 2; i < Call.Ins.Count; i++) {
+ BIDescriptor.AddInstantiationExpr(Call.Ins[i]);
+ }
+ BarrierInvariantDescriptors.Add(BIDescriptor);
+ return;
+ }
+
+ if (QKeyValue.FindBoolAttribute(Call.Proc.Attributes, "binary_barrier_invariant")) {
+ // There should be a predicate, an invariant expression, and at least one pair of
+ // instantiation expressions
+ Debug.Assert(Call.Ins.Count >= 4);
+ var BIDescriptor = new BinaryBarrierInvariantDescriptor(Call.Ins[0],
+ Expr.Neq(Call.Ins[1],
+ new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 1)),
+ Call.Attributes,
+ this, procName);
+ for (var i = 2; i < Call.Ins.Count; i += 2) {
+ BIDescriptor.AddInstantiationExprPair(Call.Ins[i], Call.Ins[i + 1]);
+ }
+ BarrierInvariantDescriptors.Add(BIDescriptor);
+ return;
+ }
+
+
+ if (Call.callee.Equals(verifier.BarrierProcedure.Name)) {
+ // Assert barrier invariants
+ foreach (var BIDescriptor in BarrierInvariantDescriptors) {
+ cs.Add(BIDescriptor.GetAssertCmd());
+ }
+ }
+
List<Expr> uniformNewIns = new List<Expr>();
List<Expr> nonUniformNewIns = new List<Expr>();
for (int i = 0; i < Call.Ins.Count; i++) {
@@ -148,29 +190,50 @@ namespace GPUVerify {
NewCallCmd.Attributes = Call.Attributes;
cs.Add(NewCallCmd);
+
+ if (Call.callee.Equals(verifier.BarrierProcedure.Name)) {
+ foreach (var BIDescriptor in BarrierInvariantDescriptors) {
+ foreach (var Instantiation in BIDescriptor.GetInstantiationCmds()) {
+ cs.Add(Instantiation);
+ }
+ }
+ BarrierInvariantDescriptors.Clear();
+ }
+
}
else if (c is AssignCmd) {
AssignCmd assign = c as AssignCmd;
- if (assign.Lhss.All(lhs =>
- lhs is SimpleAssignLhs &&
- verifier.uniformityAnalyser.IsUniform(procName, (lhs as SimpleAssignLhs).AssignedVariable.Name))) {
- cs.Add(assign);
+ var vd1 = new VariableDualiser(1, verifier.uniformityAnalyser, procName);
+ var vd2 = new VariableDualiser(2, verifier.uniformityAnalyser, procName);
+
+ List<AssignLhs> lhss1 = new List<AssignLhs>();
+ List<AssignLhs> lhss2 = new List<AssignLhs>();
+
+ List<Expr> rhss1 = new List<Expr>();
+ List<Expr> rhss2 = new List<Expr>();
+
+ foreach(var pair in assign.Lhss.Zip(assign.Rhss)) {
+ if(pair.Item1 is SimpleAssignLhs &&
+ verifier.uniformityAnalyser.IsUniform(procName,
+ (pair.Item1 as SimpleAssignLhs).AssignedVariable.Name)) {
+ lhss1.Add(pair.Item1);
+ rhss1.Add(pair.Item2);
+ } else {
+ lhss1.Add(vd1.Visit(pair.Item1.Clone() as AssignLhs) as AssignLhs);
+ lhss2.Add(vd2.Visit(pair.Item1.Clone() as AssignLhs) as AssignLhs);
+ rhss1.Add(vd1.VisitExpr(pair.Item2.Clone() as Expr));
+ rhss2.Add(vd2.VisitExpr(pair.Item2.Clone() as Expr));
+ }
}
- else {
- List<AssignLhs> newLhss = assign.Lhss.SelectMany(lhs => new AssignLhs[] {
- new VariableDualiser(1, verifier.uniformityAnalyser, procName).Visit(lhs.Clone() as AssignLhs) as AssignLhs,
- new VariableDualiser(2, verifier.uniformityAnalyser, procName).Visit(lhs.Clone() as AssignLhs) as AssignLhs
- }).ToList();
- List<Expr> newRhss = assign.Rhss.SelectMany(rhs => new Expr[] {
- new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(rhs.Clone() as Expr),
- new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitExpr(rhs.Clone() as Expr)
- }).ToList();
-
- AssignCmd newAssign = new AssignCmd(assign.tok, newLhss, newRhss);
-
- cs.Add(newAssign);
+
+ Debug.Assert(lhss1.Count > 0);
+ cs.Add(new AssignCmd(Token.NoToken, lhss1, rhss1));
+
+ if(lhss2.Count > 0) {
+ cs.Add(new AssignCmd(Token.NoToken, lhss2, rhss2));
}
+
}
else if (c is HavocCmd) {
HavocCmd havoc = c as HavocCmd;
@@ -359,4 +422,127 @@ namespace GPUVerify {
}
+ class ThreadInstantiator : Duplicator {
+
+ private Expr InstantiationExpr;
+ private int Thread;
+ private UniformityAnalyser Uni;
+ private string ProcName;
+
+ internal ThreadInstantiator(Expr InstantiationExpr, int Thread,
+ UniformityAnalyser Uni, string ProcName) {
+ this.InstantiationExpr = InstantiationExpr;
+ this.Thread = Thread;
+ this.Uni = Uni;
+ this.ProcName = ProcName;
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node) {
+ Debug.Assert(!(node.Decl is Formal));
+
+ if (GPUVerifier.IsThreadLocalIdConstant(node.Decl)) {
+ Debug.Assert(node.Decl.Name.Equals(GPUVerifier._X.Name));
+ return InstantiationExpr.Clone() as Expr;
+ }
+
+ if(node.Decl is Constant ||
+ QKeyValue.FindBoolAttribute(node.Decl.Attributes, "global") ||
+ QKeyValue.FindBoolAttribute(node.Decl.Attributes, "group_shared") ||
+ (Uni != null && Uni.IsUniform(ProcName, node.Decl.Name))) {
+ return base.VisitIdentifierExpr(node);
+ }
+
+ if (InstantiationExprIsThreadId()) {
+ return new VariableDualiser(Thread, Uni, ProcName).VisitIdentifierExpr(node);
+ }
+
+ Debug.Assert(false);
+ return null;
+ }
+
+ private bool InstantiationExprIsThreadId() {
+ return (InstantiationExpr is IdentifierExpr) &&
+ ((IdentifierExpr)InstantiationExpr).Decl.Name.Equals(GPUVerifier.MakeThreadId("X", Thread).Name);
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node) {
+ if (node.Fun is MapSelect) {
+ Debug.Assert((node.Fun as MapSelect).Arity == 1);
+ Debug.Assert(node.Args[0] is IdentifierExpr);
+ var v = (node.Args[0] as IdentifierExpr).Decl;
+ if (QKeyValue.FindBoolAttribute(v.Attributes, "group_shared")) {
+ return new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
+ new ExprSeq(new Expr[] { new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
+ new ExprSeq(new Expr[] { node.Args[0], GPUVerifier.GroupSharedIndexingExpr(Thread) })), VisitExpr(node.Args[1]) }));
+ }
+ }
+ return base.VisitNAryExpr(node);
+ }
+
+
+ }
+
+
+
+ class ThreadPairInstantiator : Duplicator {
+
+ private GPUVerifier verifier;
+ private Tuple<Expr, Expr> InstantiationExprs;
+ private int Thread;
+
+ internal ThreadPairInstantiator(GPUVerifier verifier, Expr InstantiationExpr1, Expr InstantiationExpr2, int Thread) {
+ this.verifier = verifier;
+ this.InstantiationExprs = new Tuple<Expr, Expr>(InstantiationExpr1, InstantiationExpr2);
+ this.Thread = Thread;
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node) {
+ Debug.Assert(!(node.Decl is Formal));
+
+ if (GPUVerifier.IsThreadLocalIdConstant(node.Decl)) {
+ Debug.Assert(node.Decl.Name.Equals(GPUVerifier._X.Name));
+ return InstantiationExprs.Item1.Clone() as Expr;
+ }
+
+ Debug.Assert(node.Decl is Constant ||
+ verifier.KernelArrayInfo.getGroupSharedArrays().Contains(node.Decl) ||
+ verifier.KernelArrayInfo.getGlobalArrays().Contains(node.Decl));
+
+ return base.VisitIdentifierExpr(node);
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node) {
+ if (node.Fun is MapSelect) {
+ Debug.Assert((node.Fun as MapSelect).Arity == 1);
+ Debug.Assert(node.Args[0] is IdentifierExpr);
+ var v = (node.Args[0] as IdentifierExpr).Decl;
+
+ if (QKeyValue.FindBoolAttribute(v.Attributes, "group_shared")) {
+ return new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
+ new ExprSeq(new Expr[] { new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
+ new ExprSeq(new Expr[] { node.Args[0], GPUVerifier.GroupSharedIndexingExpr(Thread) })), VisitExpr(node.Args[1]) }));
+ }
+ }
+
+ if (node.Fun is FunctionCall) {
+ FunctionCall call = node.Fun as FunctionCall;
+
+ // Alternate instantiation order for "other thread" functions.
+ // Note that we do not alternatve the "Thread" field, as we are not switching the
+ // thread for which instantiation is being performed
+ if (VariableDualiser.otherFunctionNames.Contains(call.Func.Name)) {
+ return new ThreadPairInstantiator(verifier, InstantiationExprs.Item2, InstantiationExprs.Item1, Thread)
+ .VisitExpr(node.Args[0]);
+ }
+
+ }
+
+ return base.VisitNAryExpr(node);
+ }
+
+
+ }
+
+
+
}
diff --git a/Source/GPUVerify/LoopInvariantGenerator.cs b/Source/GPUVerify/LoopInvariantGenerator.cs
index 1c15f5e6..a465a98a 100644
--- a/Source/GPUVerify/LoopInvariantGenerator.cs
+++ b/Source/GPUVerify/LoopInvariantGenerator.cs
@@ -1,258 +1,258 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-using System.Diagnostics;
-
-using GPUVerify.InvariantGenerationRules;
-
-namespace GPUVerify {
- class LoopInvariantGenerator {
- private GPUVerifier verifier;
- private Implementation Impl;
-
- private List<InvariantGenerationRule> invariantGenerationRules;
-
- LoopInvariantGenerator(GPUVerifier verifier, Implementation Impl) {
- this.verifier = verifier;
- this.Impl = Impl;
-
- invariantGenerationRules = new List<InvariantGenerationRule>();
- invariantGenerationRules.Add(new PowerOfTwoInvariantGenerator(verifier));
- invariantGenerationRules.Add(new LoopVariableBoundsInvariantGenerator(verifier));
- }
-
- public static void PreInstrument(GPUVerifier verifier, Implementation impl) {
- foreach (var region in verifier.RootRegion(impl).SubRegions()) {
- GenerateCandidateForReducedStrengthStrideVariables(verifier, impl, region);
- }
- }
-
- private static void GenerateCandidateForReducedStrengthStrideVariables(GPUVerifier verifier, Implementation impl, IRegion region) {
- var rsa = verifier.reducedStrengthAnalyses[impl];
- foreach (string lc in rsa.StridedLoopCounters(region.Identifier())) {
- var sc = rsa.GetStrideConstraint(lc);
- Variable lcVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, lc,
- Microsoft.Boogie.Type.GetBvType(32)));
- var lcExpr = new IdentifierExpr(Token.NoToken, lcVariable);
- var lcPred = sc.MaybeBuildPredicate(verifier, lcExpr);
-
- if (lcPred != null) {
- verifier.AddCandidateInvariant(region, lcPred, "variable " + lc + " is strided");
- }
- }
- }
-
- public static void PostInstrument(GPUVerifier verifier, Implementation Impl, List<Expr> UserSuppliedInvariants) {
- new LoopInvariantGenerator(verifier, Impl).PostInstrument(UserSuppliedInvariants);
- }
-
- internal void PostInstrument(List<Expr> UserSuppliedInvariants) {
- HashSet<Variable> LocalVars = new HashSet<Variable>();
- foreach (Variable v in Impl.LocVars) {
- LocalVars.Add(v);
- }
- foreach (Variable v in Impl.InParams) {
- LocalVars.Add(v);
- }
- foreach (Variable v in Impl.OutParams) {
- LocalVars.Add(v);
- }
-
- AddCandidateInvariants(verifier.RootRegion(Impl), LocalVars, UserSuppliedInvariants, Impl);
-
- }
-
- private void AddEqualityCandidateInvariant(IRegion region, string LoopPredicate, Variable v) {
- verifier.AddCandidateInvariant(region,
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, new VariableDualiser(1, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Token.NoToken, new VariableDualiser(2, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable))
- ), "equality");
- }
-
- private void AddPredicatedEqualityCandidateInvariant(IRegion region, string LoopPredicate, Variable v) {
- verifier.AddCandidateInvariant(region, Expr.Imp(
- Expr.And(
- new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$1", Microsoft.Boogie.Type.Int))),
- new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$2", Microsoft.Boogie.Type.Int)))
- ),
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, new VariableDualiser(1, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Token.NoToken, new VariableDualiser(2, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable))
- )), "predicated equality");
- }
-
- private Dictionary<string, int> GetAssignmentCounts(Implementation impl) {
-
- Dictionary<string, int> result = new Dictionary<string, int>();
-
- foreach (var c in verifier.RootRegion(impl).Cmds()) {
- if (c is AssignCmd) {
- var aCmd = (AssignCmd)c;
- HashSet<string> alreadySeenInThisAssignment = new HashSet<string>();
- foreach (var a in aCmd.Lhss) {
- if (a is SimpleAssignLhs) {
- var v = GPUVerifier.StripThreadIdentifier(
- ((SimpleAssignLhs)a).AssignedVariable.Name);
- if (!alreadySeenInThisAssignment.Contains(v)) {
- if (result.ContainsKey(v)) {
- result[v]++;
- }
- else {
- result[v] = 1;
- }
- alreadySeenInThisAssignment.Add(v);
- }
- }
- }
- }
- }
- return result;
- }
-
-
- private void AddBarrierDivergenceCandidates(HashSet<Variable> LocalVars, Implementation Impl, IRegion region)
- {
-
- if (!verifier.ContainsBarrierCall(region))
- {
- return;
- }
-
- Expr guard = region.Guard();
- if (verifier.uniformityAnalyser.IsUniform(Impl.Name, guard))
- {
- return;
- }
-
- if (IsDisjunctionOfPredicates(guard))
- {
- string LoopPredicate = ((guard as NAryExpr).Args[0] as IdentifierExpr).Name;
- LoopPredicate = LoopPredicate.Substring(0, LoopPredicate.IndexOf('$'));
-
- verifier.AddCandidateInvariant(region, Expr.Eq(
- // Int type used here, but it doesn't matter as we will print and then re-parse the program
- new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$1", Microsoft.Boogie.Type.Int))),
- new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$2", Microsoft.Boogie.Type.Int)))
- ), "loop predicate equality");
-
- Dictionary<string, int> assignmentCounts = GetAssignmentCounts(Impl);
-
- HashSet<string> alreadyConsidered = new HashSet<String>();
-
- foreach (var v in LocalVars)
- {
- string lv = GPUVerifier.StripThreadIdentifier(v.Name);
- if (alreadyConsidered.Contains(lv)) {
- continue;
- }
- alreadyConsidered.Add(lv);
-
- if (verifier.uniformityAnalyser.IsUniform(Impl.Name, v.Name))
- {
- continue;
- }
-
- if (GPUVerifier.IsPredicate(lv))
- {
- continue;
- }
-
- if (!assignmentCounts.ContainsKey(lv) || assignmentCounts[lv] <= 1) {
- continue;
- }
-
- if (!verifier.ContainsNamedVariable(
- GetModifiedVariables(region), lv))
- {
- continue;
- }
-
- AddPredicatedEqualityCandidateInvariant(region, LoopPredicate, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, lv, Microsoft.Boogie.Type.Int)));
- }
-
- if (CommandLineOptions.ArrayEqualities)
- {
- foreach (Variable v in verifier.KernelArrayInfo.getAllNonLocalArrays())
- {
- if (!verifier.ArrayModelledAdversarially(v))
- {
- AddEqualityCandidateInvariant(region, LoopPredicate, v);
- }
- }
- }
- }
- }
-
- private static bool IsDisjunctionOfPredicates(Expr guard) {
- if (!(guard is NAryExpr)) {
- return false;
- }
- NAryExpr nary = (NAryExpr)guard;
- if(nary.Args.Length != 2) {
- return false;
- }
- if(!(nary.Fun is BinaryOperator)) {
- return false;
- }
- BinaryOperator binOp = (BinaryOperator)nary.Fun;
- if(binOp.Op != BinaryOperator.Opcode.Or) {
- return false;
- }
- if(!(nary.Args[0] is IdentifierExpr && nary.Args[1] is IdentifierExpr)) {
- return false;
- }
- return GPUVerifier.IsPredicate(GPUVerifier.StripThreadIdentifier(
- ((IdentifierExpr)nary.Args[0]).Name)) &&
- GPUVerifier.IsPredicate(GPUVerifier.StripThreadIdentifier(
- ((IdentifierExpr)nary.Args[1]).Name));
- }
-
- private void AddCandidateInvariants(IRegion region, HashSet<Variable> LocalVars, List<Expr> UserSuppliedInvariants, Implementation Impl) {
- foreach (IRegion subregion in region.SubRegions()) {
- foreach (InvariantGenerationRule r in invariantGenerationRules) {
- r.GenerateCandidates(Impl, subregion);
- }
-
- AddBarrierDivergenceCandidates(LocalVars, Impl, subregion);
-
- verifier.RaceInstrumenter.AddRaceCheckingCandidateInvariants(Impl, subregion);
-
- AddUserSuppliedInvariants(subregion, UserSuppliedInvariants, Impl);
- }
- }
-
- private void AddUserSuppliedInvariants(IRegion region, List<Expr> UserSuppliedInvariants, Implementation Impl) {
- foreach (Expr e in UserSuppliedInvariants) {
- /*
- wc.Invariants.Add(new AssertCmd(wc.tok, e));
- bool OK = verifier.ProgramIsOK(Impl);
- wc.Invariants.RemoveAt(wc.Invariants.Count - 1);
- if (OK)
- {
- verifier.AddCandidateInvariant(wc, e, "user supplied");
- }
- */
- verifier.AddCandidateInvariant(region, e, "user supplied");
- }
- }
-
- internal static HashSet<Variable> GetModifiedVariables(IRegion region) {
- HashSet<Variable> result = new HashSet<Variable>();
-
- foreach (Cmd c in region.Cmds()) {
- VariableSeq vars = new VariableSeq();
- c.AddAssignedVariables(vars);
- foreach (Variable v in vars) {
- result.Add(v);
- }
- }
-
- return result;
- }
-
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using Microsoft.Basetypes;
+using System.Diagnostics;
+
+using GPUVerify.InvariantGenerationRules;
+
+namespace GPUVerify {
+ class LoopInvariantGenerator {
+ private GPUVerifier verifier;
+ private Implementation Impl;
+
+ private List<InvariantGenerationRule> invariantGenerationRules;
+
+ LoopInvariantGenerator(GPUVerifier verifier, Implementation Impl) {
+ this.verifier = verifier;
+ this.Impl = Impl;
+
+ invariantGenerationRules = new List<InvariantGenerationRule>();
+ invariantGenerationRules.Add(new PowerOfTwoInvariantGenerator(verifier));
+ invariantGenerationRules.Add(new LoopVariableBoundsInvariantGenerator(verifier));
+ }
+
+ public static void PreInstrument(GPUVerifier verifier, Implementation impl) {
+ foreach (var region in verifier.RootRegion(impl).SubRegions()) {
+ GenerateCandidateForReducedStrengthStrideVariables(verifier, impl, region);
+ }
+ }
+
+ private static void GenerateCandidateForReducedStrengthStrideVariables(GPUVerifier verifier, Implementation impl, IRegion region) {
+ var rsa = verifier.reducedStrengthAnalyses[impl];
+ foreach (string lc in rsa.StridedLoopCounters(region.Identifier())) {
+ var sc = rsa.GetStrideConstraint(lc);
+ Variable lcVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, lc,
+ Microsoft.Boogie.Type.GetBvType(32)));
+ var lcExpr = new IdentifierExpr(Token.NoToken, lcVariable);
+ var lcPred = sc.MaybeBuildPredicate(verifier, lcExpr);
+
+ if (lcPred != null) {
+ verifier.AddCandidateInvariant(region, lcPred, "variable " + lc + " is strided");
+ }
+ }
+ }
+
+ public static void PostInstrument(GPUVerifier verifier, Implementation Impl, List<Expr> UserSuppliedInvariants) {
+ new LoopInvariantGenerator(verifier, Impl).PostInstrument(UserSuppliedInvariants);
+ }
+
+ internal void PostInstrument(List<Expr> UserSuppliedInvariants) {
+ HashSet<Variable> LocalVars = new HashSet<Variable>();
+ foreach (Variable v in Impl.LocVars) {
+ LocalVars.Add(v);
+ }
+ foreach (Variable v in Impl.InParams) {
+ LocalVars.Add(v);
+ }
+ foreach (Variable v in Impl.OutParams) {
+ LocalVars.Add(v);
+ }
+
+ AddCandidateInvariants(verifier.RootRegion(Impl), LocalVars, UserSuppliedInvariants, Impl);
+
+ }
+
+ private void AddEqualityCandidateInvariant(IRegion region, string LoopPredicate, Variable v) {
+ verifier.AddCandidateInvariant(region,
+ Expr.Eq(
+ new IdentifierExpr(Token.NoToken, new VariableDualiser(1, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)),
+ new IdentifierExpr(Token.NoToken, new VariableDualiser(2, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable))
+ ), "equality");
+ }
+
+ private void AddPredicatedEqualityCandidateInvariant(IRegion region, string LoopPredicate, Variable v) {
+ verifier.AddCandidateInvariant(region, Expr.Imp(
+ Expr.And(
+ new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$1", Microsoft.Boogie.Type.Int))),
+ new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$2", Microsoft.Boogie.Type.Int)))
+ ),
+ Expr.Eq(
+ new IdentifierExpr(Token.NoToken, new VariableDualiser(1, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)),
+ new IdentifierExpr(Token.NoToken, new VariableDualiser(2, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable))
+ )), "predicated equality");
+ }
+
+ private Dictionary<string, int> GetAssignmentCounts(Implementation impl) {
+
+ Dictionary<string, int> result = new Dictionary<string, int>();
+
+ foreach (var c in verifier.RootRegion(impl).Cmds()) {
+ if (c is AssignCmd) {
+ var aCmd = (AssignCmd)c;
+ HashSet<string> alreadySeenInThisAssignment = new HashSet<string>();
+ foreach (var a in aCmd.Lhss) {
+ if (a is SimpleAssignLhs) {
+ var v = GPUVerifier.StripThreadIdentifier(
+ ((SimpleAssignLhs)a).AssignedVariable.Name);
+ if (!alreadySeenInThisAssignment.Contains(v)) {
+ if (result.ContainsKey(v)) {
+ result[v]++;
+ }
+ else {
+ result[v] = 1;
+ }
+ alreadySeenInThisAssignment.Add(v);
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+
+ private void AddBarrierDivergenceCandidates(HashSet<Variable> LocalVars, Implementation Impl, IRegion region)
+ {
+
+ if (!verifier.ContainsBarrierCall(region))
+ {
+ return;
+ }
+
+ Expr guard = region.Guard();
+ if (guard != null && verifier.uniformityAnalyser.IsUniform(Impl.Name, guard))
+ {
+ return;
+ }
+
+ if (IsDisjunctionOfPredicates(guard))
+ {
+ string LoopPredicate = ((guard as NAryExpr).Args[0] as IdentifierExpr).Name;
+ LoopPredicate = LoopPredicate.Substring(0, LoopPredicate.IndexOf('$'));
+
+ verifier.AddCandidateInvariant(region, Expr.Eq(
+ // Int type used here, but it doesn't matter as we will print and then re-parse the program
+ new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$1", Microsoft.Boogie.Type.Int))),
+ new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$2", Microsoft.Boogie.Type.Int)))
+ ), "loop predicate equality");
+
+ Dictionary<string, int> assignmentCounts = GetAssignmentCounts(Impl);
+
+ HashSet<string> alreadyConsidered = new HashSet<String>();
+
+ foreach (var v in LocalVars)
+ {
+ string lv = GPUVerifier.StripThreadIdentifier(v.Name);
+ if (alreadyConsidered.Contains(lv)) {
+ continue;
+ }
+ alreadyConsidered.Add(lv);
+
+ if (verifier.uniformityAnalyser.IsUniform(Impl.Name, v.Name))
+ {
+ continue;
+ }
+
+ if (GPUVerifier.IsPredicate(lv))
+ {
+ continue;
+ }
+
+ if (!assignmentCounts.ContainsKey(lv) || assignmentCounts[lv] <= 1) {
+ continue;
+ }
+
+ if (!verifier.ContainsNamedVariable(
+ GetModifiedVariables(region), lv))
+ {
+ continue;
+ }
+
+ AddPredicatedEqualityCandidateInvariant(region, LoopPredicate, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, lv, Microsoft.Boogie.Type.Int)));
+ }
+
+ if (CommandLineOptions.ArrayEqualities)
+ {
+ foreach (Variable v in verifier.KernelArrayInfo.getAllNonLocalArrays())
+ {
+ if (!verifier.ArrayModelledAdversarially(v))
+ {
+ AddEqualityCandidateInvariant(region, LoopPredicate, v);
+ }
+ }
+ }
+ }
+ }
+
+ private static bool IsDisjunctionOfPredicates(Expr guard) {
+ if (!(guard is NAryExpr)) {
+ return false;
+ }
+ NAryExpr nary = (NAryExpr)guard;
+ if(nary.Args.Length != 2) {
+ return false;
+ }
+ if(!(nary.Fun is BinaryOperator)) {
+ return false;
+ }
+ BinaryOperator binOp = (BinaryOperator)nary.Fun;
+ if(binOp.Op != BinaryOperator.Opcode.Or) {
+ return false;
+ }
+ if(!(nary.Args[0] is IdentifierExpr && nary.Args[1] is IdentifierExpr)) {
+ return false;
+ }
+ return GPUVerifier.IsPredicate(GPUVerifier.StripThreadIdentifier(
+ ((IdentifierExpr)nary.Args[0]).Name)) &&
+ GPUVerifier.IsPredicate(GPUVerifier.StripThreadIdentifier(
+ ((IdentifierExpr)nary.Args[1]).Name));
+ }
+
+ private void AddCandidateInvariants(IRegion region, HashSet<Variable> LocalVars, List<Expr> UserSuppliedInvariants, Implementation Impl) {
+ foreach (IRegion subregion in region.SubRegions()) {
+ foreach (InvariantGenerationRule r in invariantGenerationRules) {
+ r.GenerateCandidates(Impl, subregion);
+ }
+
+ AddBarrierDivergenceCandidates(LocalVars, Impl, subregion);
+
+ verifier.RaceInstrumenter.AddRaceCheckingCandidateInvariants(Impl, subregion);
+
+ AddUserSuppliedInvariants(subregion, UserSuppliedInvariants, Impl);
+ }
+ }
+
+ private void AddUserSuppliedInvariants(IRegion region, List<Expr> UserSuppliedInvariants, Implementation Impl) {
+ foreach (Expr e in UserSuppliedInvariants) {
+ /*
+ wc.Invariants.Add(new AssertCmd(wc.tok, e));
+ bool OK = verifier.ProgramIsOK(Impl);
+ wc.Invariants.RemoveAt(wc.Invariants.Count - 1);
+ if (OK)
+ {
+ verifier.AddCandidateInvariant(wc, e, "user supplied");
+ }
+ */
+ verifier.AddCandidateInvariant(region, e, "user supplied");
+ }
+ }
+
+ internal static HashSet<Variable> GetModifiedVariables(IRegion region) {
+ HashSet<Variable> result = new HashSet<Variable>();
+
+ foreach (Cmd c in region.Cmds()) {
+ VariableSeq vars = new VariableSeq();
+ c.AddAssignedVariables(vars);
+ foreach (Variable v in vars) {
+ result.Add(v);
+ }
+ }
+
+ return result;
+ }
+
+ }
+}
diff --git a/Source/GPUVerify/NonLocalAccessCollector.cs b/Source/GPUVerify/NonLocalAccessCollector.cs
index 6a934899..d1361ff4 100644
--- a/Source/GPUVerify/NonLocalAccessCollector.cs
+++ b/Source/GPUVerify/NonLocalAccessCollector.cs
@@ -70,7 +70,6 @@ namespace GPUVerify
return collector.Accesses.Count > 0;
}
-
public override Expr VisitNAryExpr(NAryExpr node)
{
if (IsNonLocalAccess(node, NonLocalState))
diff --git a/Source/GPUVerify/NullRaceInstrumenter.cs b/Source/GPUVerify/NullRaceInstrumenter.cs
index 0d0ee41d..6452331f 100644
--- a/Source/GPUVerify/NullRaceInstrumenter.cs
+++ b/Source/GPUVerify/NullRaceInstrumenter.cs
@@ -1,52 +1,67 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-
-namespace GPUVerify
-{
- class NullRaceInstrumenter : IRaceInstrumenter
- {
-
- public void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region)
- {
-
- }
-
- public void AddKernelPrecondition()
- {
-
- }
-
- public void AddRaceCheckingInstrumentation()
- {
-
- }
-
- public Microsoft.Boogie.BigBlock MakeResetReadWriteSetStatements(Variable v, int Thread)
- {
- return new BigBlock(Token.NoToken, null, new CmdSeq(), null, null);
- }
-
- public void AddRaceCheckingCandidateRequires(Procedure Proc)
- {
-
- }
-
- public void AddRaceCheckingCandidateEnsures(Procedure Proc)
- {
-
- }
-
- public void AddRaceCheckingDeclarations()
- {
-
- }
- public void AddSourceLocationLoopInvariants(Implementation impl, IRegion region)
- {
-
- }
-
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+
+namespace GPUVerify
+{
+ class NullRaceInstrumenter : IRaceInstrumenter
+ {
+
+ public void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region)
+ {
+
+ }
+
+ public void AddKernelPrecondition()
+ {
+
+ }
+
+ public void AddRaceCheckingInstrumentation()
+ {
+
+ }
+
+ public Microsoft.Boogie.BigBlock MakeResetReadWriteSetStatements(Variable v, Expr ResetCondition)
+ {
+ return new BigBlock(Token.NoToken, null, new CmdSeq(), null, null);
+ }
+
+ public void AddRaceCheckingCandidateRequires(Procedure Proc)
+ {
+
+ }
+
+ public void AddRaceCheckingCandidateEnsures(Procedure Proc)
+ {
+
+ }
+
+ public void AddRaceCheckingDeclarations()
+ {
+
+ }
+
+ public void AddSourceLocationLoopInvariants(Implementation impl, IRegion region)
+ {
+
+ }
+
+ public void DoHoudiniPointerAnalysis(Procedure Proc)
+ {
+
+ }
+
+ public void AddStandardSourceVariablePreconditions()
+ {
+
+ }
+
+ public void AddStandardSourceVariablePostconditions()
+ {
+
+ }
+ }
+}
diff --git a/Source/GPUVerify/RaceInstrumenter.cs b/Source/GPUVerify/RaceInstrumenter.cs
index 1ec8f7ec..f3b9194b 100644
--- a/Source/GPUVerify/RaceInstrumenter.cs
+++ b/Source/GPUVerify/RaceInstrumenter.cs
@@ -1,1048 +1,1133 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-
-namespace GPUVerify {
- class RaceInstrumenter : IRaceInstrumenter {
- protected GPUVerifier verifier;
-
- private QKeyValue SourceLocationAttributes = null;
-
- private int CurrStmtNo = 1;
-
- private Dictionary<string, List<int>> ReadAccessSourceLocations = new Dictionary<string, List<int>>();
-
- private Dictionary<string, List<int>> WriteAccessSourceLocations = new Dictionary<string, List<int>>();
-
- public IKernelArrayInfo NonLocalStateToCheck;
-
- private Dictionary<string, Procedure> RaceCheckingProcedures = new Dictionary<string, Procedure>();
-
- public void setVerifier(GPUVerifier verifier) {
- this.verifier = verifier;
- NonLocalStateToCheck = new KernelArrayInfoLists();
- foreach (Variable v in verifier.KernelArrayInfo.getGlobalArrays()) {
- NonLocalStateToCheck.getGlobalArrays().Add(v);
- }
- foreach (Variable v in verifier.KernelArrayInfo.getGroupSharedArrays()) {
- NonLocalStateToCheck.getGroupSharedArrays().Add(v);
- }
- }
-
- private void AddNoReadOrWriteCandidateInvariants(IRegion region, Variable v) {
- // Reasoning: if READ_HAS_OCCURRED_v is not in the modifies set for the
- // loop then there is no point adding an invariant
- //
- // If READ_HAS_OCCURRED_v is in the modifies set, but the loop does not
- // contain a barrier, then it is almost certain that a read CAN be
- // pending at the loop head, so the invariant will not hold
- //
- // If there is a barrier in the loop body then READ_HAS_OCCURRED_v will
- // be in the modifies set, but there may not be a live read at the loop
- // head, so it is worth adding the loop invariant candidate.
- //
- // The same reasoning applies for WRITE
-
- if (verifier.ContainsBarrierCall(region)) {
- if (verifier.ContainsNamedVariable(
- LoopInvariantGenerator.GetModifiedVariables(region), GPUVerifier.MakeAccessHasOccurredVariableName(v.Name, "READ"))) {
- AddNoReadOrWriteCandidateInvariant(region, v, "READ");
- }
-
- if (verifier.ContainsNamedVariable(
- LoopInvariantGenerator.GetModifiedVariables(region), GPUVerifier.MakeAccessHasOccurredVariableName(v.Name, "WRITE"))) {
- AddNoReadOrWriteCandidateInvariant(region, v, "WRITE");
- }
- }
- }
-
- private void AddNoReadOrWriteCandidateRequires(Procedure Proc, Variable v) {
- AddNoReadOrWriteCandidateRequires(Proc, v, "READ", "1");
- AddNoReadOrWriteCandidateRequires(Proc, v, "WRITE", "1");
- }
-
- private void AddNoReadOrWriteCandidateEnsures(Procedure Proc, Variable v) {
- AddNoReadOrWriteCandidateEnsures(Proc, v, "READ", "1");
- AddNoReadOrWriteCandidateEnsures(Proc, v, "WRITE", "1");
- }
-
- private void AddNoReadOrWriteCandidateInvariant(IRegion region, Variable v, string ReadOrWrite) {
- Expr candidate = NoReadOrWriteExpr(v, ReadOrWrite, "1");
- verifier.AddCandidateInvariant(region, candidate, "no " + ReadOrWrite.ToLower());
- }
-
- public void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region) {
- foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
- AddNoReadOrWriteCandidateInvariants(region, v);
- AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(impl, region, v, "READ");
- AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(impl, region, v, "WRITE");
- AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "READ", CollectOffsetPredicates(impl, region, v, "READ"));
- AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "WRITE", CollectOffsetPredicates(impl, region, v, "WRITE"));
- }
- }
-
- private void AddAccessRelatedCandidateInvariant(IRegion region, string accessKind, Expr candidateInvariantExpr, string procName, string tag) {
- Expr candidate = new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(candidateInvariantExpr.Clone() as Expr);
- verifier.AddCandidateInvariant(region, candidate, tag);
- }
-
- private bool DoesNotReferTo(Expr expr, string v) {
- FindReferencesToNamedVariableVisitor visitor = new FindReferencesToNamedVariableVisitor(v);
- visitor.VisitExpr(expr);
- return !visitor.found;
- }
-
- private List<Expr> CollectOffsetPredicates(Implementation impl, IRegion region, Variable v, string accessType) {
- var offsetVar = new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeOffsetVariable(v.Name, accessType));
- var offsetExpr = new IdentifierExpr(Token.NoToken, offsetVar);
- var offsetPreds = new List<Expr>();
-
- foreach (var offset in GetOffsetsAccessed(region, v, accessType)) {
- bool isConstant;
- var def = verifier.varDefAnalyses[impl].SubstDefinitions(offset, impl.Name, out isConstant);
- if (def == null)
- continue;
-
- if (isConstant) {
- offsetPreds.Add(Expr.Eq(offsetExpr, def));
- }
- else {
- var sc = StrideConstraint.FromExpr(verifier, impl, def);
- var pred = sc.MaybeBuildPredicate(verifier, offsetExpr);
- if (pred != null)
- offsetPreds.Add(pred);
- }
- }
-
- return offsetPreds;
- }
-
- private void AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(Implementation impl, IRegion region, Variable v, string accessType) {
- KeyValuePair<IdentifierExpr, Expr> iLessThanC = GetILessThanC(region.Guard());
- if (iLessThanC.Key != null) {
- foreach (Expr e in GetOffsetsAccessed(region, v, accessType)) {
- if (HasFormIPlusLocalIdTimesC(e, iLessThanC, impl)) {
- AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(region, v, iLessThanC.Value, accessType);
- break;
- }
- }
-
- foreach (Expr e in GetOffsetsAccessed(region, v, accessType)) {
- if (HasFormIPlusGlobalIdTimesC(e, iLessThanC, impl)) {
- AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(region, v, iLessThanC.Value, accessType);
- break;
- }
- }
-
- }
-
-
- }
-
- private bool HasFormIPlusLocalIdTimesC(Expr e, KeyValuePair<IdentifierExpr, Expr> iLessThanC, Implementation impl) {
- if (!(e is NAryExpr)) {
- return false;
- }
-
- NAryExpr nary = e as NAryExpr;
-
- if (!nary.Fun.FunctionName.Equals("BV32_ADD")) {
- return false;
- }
-
- return (SameIdentifierExpression(nary.Args[0], iLessThanC.Key) &&
- IsLocalIdTimesConstant(nary.Args[1], iLessThanC.Value, impl)) ||
- (SameIdentifierExpression(nary.Args[1], iLessThanC.Key) &&
- IsLocalIdTimesConstant(nary.Args[0], iLessThanC.Value, impl));
- }
-
- private bool IsLocalIdTimesConstant(Expr maybeLocalIdTimesConstant, Expr constant, Implementation impl) {
- if (!(maybeLocalIdTimesConstant is NAryExpr)) {
- return false;
- }
- NAryExpr nary = maybeLocalIdTimesConstant as NAryExpr;
- if (!nary.Fun.FunctionName.Equals("BV32_MUL")) {
- return false;
- }
-
- return
- (SameConstant(nary.Args[0], constant) && verifier.IsLocalId(nary.Args[1], 0, impl)) ||
- (SameConstant(nary.Args[1], constant) && verifier.IsLocalId(nary.Args[0], 0, impl));
- }
-
-
- private bool HasFormIPlusGlobalIdTimesC(Expr e, KeyValuePair<IdentifierExpr, Expr> iLessThanC, Implementation impl) {
- if (!(e is NAryExpr)) {
- return false;
- }
-
- NAryExpr nary = e as NAryExpr;
-
- if (!nary.Fun.FunctionName.Equals("BV32_ADD")) {
- return false;
- }
-
- return (SameIdentifierExpression(nary.Args[0], iLessThanC.Key) &&
- IsGlobalIdTimesConstant(nary.Args[1], iLessThanC.Value, impl)) ||
- (SameIdentifierExpression(nary.Args[1], iLessThanC.Key) &&
- IsGlobalIdTimesConstant(nary.Args[0], iLessThanC.Value, impl));
- }
-
- private bool IsGlobalIdTimesConstant(Expr maybeGlobalIdTimesConstant, Expr constant, Implementation impl) {
- if (!(maybeGlobalIdTimesConstant is NAryExpr)) {
- return false;
- }
- NAryExpr nary = maybeGlobalIdTimesConstant as NAryExpr;
- if (!nary.Fun.FunctionName.Equals("BV32_MUL")) {
- return false;
- }
-
- return
- (SameConstant(nary.Args[0], constant) && verifier.IsGlobalId(nary.Args[1], 0, impl)) ||
- (SameConstant(nary.Args[1], constant) && verifier.IsGlobalId(nary.Args[0], 0, impl));
- }
-
-
- private bool SameConstant(Expr expr, Expr constant) {
- if (constant is IdentifierExpr) {
- IdentifierExpr identifierExpr = constant as IdentifierExpr;
- Debug.Assert(identifierExpr.Decl is Constant);
- return expr is IdentifierExpr && (expr as IdentifierExpr).Decl is Constant && (expr as IdentifierExpr).Decl.Name.Equals(identifierExpr.Decl.Name);
- }
- else {
- Debug.Assert(constant is LiteralExpr);
- LiteralExpr literalExpr = constant as LiteralExpr;
- if (!(expr is LiteralExpr)) {
- return false;
- }
- if (!(literalExpr.Val is BvConst) || !((expr as LiteralExpr).Val is BvConst)) {
- return false;
- }
-
- return (literalExpr.Val as BvConst).Value.ToInt == ((expr as LiteralExpr).Val as BvConst).Value.ToInt;
- }
- }
-
- private bool SameIdentifierExpression(Expr expr, IdentifierExpr identifierExpr) {
- if (!(expr is IdentifierExpr)) {
- return false;
- }
- return (expr as IdentifierExpr).Decl.Name.Equals(identifierExpr.Name);
- }
-
- private KeyValuePair<IdentifierExpr, Expr> GetILessThanC(Expr expr) {
-
- if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("bv32_to_bool")) {
- expr = (expr as NAryExpr).Args[0];
- }
-
- if (!(expr is NAryExpr)) {
- return new KeyValuePair<IdentifierExpr, Expr>(null, null);
- }
-
- NAryExpr nary = expr as NAryExpr;
-
- if (!(nary.Fun.FunctionName.Equals("BV32_C_LT") || nary.Fun.FunctionName.Equals("BV32_LT"))) {
- return new KeyValuePair<IdentifierExpr, Expr>(null, null);
- }
-
- if (!(nary.Args[0] is IdentifierExpr)) {
- return new KeyValuePair<IdentifierExpr, Expr>(null, null);
- }
-
- if (!IsConstant(nary.Args[1])) {
- return new KeyValuePair<IdentifierExpr, Expr>(null, null);
- }
-
- return new KeyValuePair<IdentifierExpr, Expr>(nary.Args[0] as IdentifierExpr, nary.Args[1]);
-
- }
-
- private static bool IsConstant(Expr e) {
- return ((e is IdentifierExpr && (e as IdentifierExpr).Decl is Constant) || e is LiteralExpr);
- }
-
- private void AddReadOrWrittenOffsetIsThreadIdCandidateRequires(Procedure Proc, Variable v) {
- AddAccessedOffsetIsThreadLocalIdCandidateRequires(Proc, v, "WRITE", 1);
- AddAccessedOffsetIsThreadLocalIdCandidateRequires(Proc, v, "READ", 1);
- }
-
- private void AddReadOrWrittenOffsetIsThreadIdCandidateEnsures(Procedure Proc, Variable v) {
- AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Proc, v, "WRITE", 1);
- AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Proc, v, "READ", 1);
- }
-
- public void AddKernelPrecondition() {
- foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
- AddRequiresNoPendingAccess(v);
- AddRequiresSourceAccessZero(v);
-
- if (!verifier.ArrayModelledAdversarially(v)) {
- IdentifierExpr v1 = new IdentifierExpr(Token.NoToken, new VariableDualiser(1, null, null).VisitVariable(v.Clone() as Variable));
- IdentifierExpr v2 = new IdentifierExpr(Token.NoToken, new VariableDualiser(2, null, null).VisitVariable(v.Clone() as Variable));
- verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.Eq(v1, v2)));
- }
- }
- }
-
- public void AddRaceCheckingInstrumentation() {
-
- foreach (Declaration d in verifier.Program.TopLevelDeclarations) {
- if (d is Implementation) {
- AddRaceCheckCalls(d as Implementation);
- }
- }
-
- }
-
- private void AddRaceCheckingDecsAndProcsForVar(Variable v) {
- AddLogRaceDeclarations(v, "READ");
- AddLogRaceDeclarations(v, "WRITE");
- AddLogAccessProcedure(v, "READ");
- AddCheckAccessProcedure(v, "READ");
- AddLogAccessProcedure(v, "WRITE");
- AddCheckAccessProcedure(v, "WRITE");
- }
-
- private StmtList AddRaceCheckCalls(StmtList stmtList) {
- Contract.Requires(stmtList != null);
-
- StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
-
- foreach (BigBlock bodyBlock in stmtList.BigBlocks) {
- result.BigBlocks.Add(AddRaceCheckCalls(bodyBlock));
- }
- return result;
- }
-
- private Block AddRaceCheckCalls(Block b) {
- b.Cmds = AddRaceCheckCalls(b.Cmds);
- return b;
- }
-
- private void AddRaceCheckCalls(Implementation impl) {
- if (CommandLineOptions.Unstructured)
- impl.Blocks = impl.Blocks.Select(AddRaceCheckCalls).ToList();
- else
- impl.StructuredStmts = AddRaceCheckCalls(impl.StructuredStmts);
- }
-
- private CmdSeq AddRaceCheckCalls(CmdSeq cs) {
- var result = new CmdSeq();
- foreach (Cmd c in cs) {
- result.Add(c);
-
- if (c is AssertCmd) {
- AssertCmd assertion = c as AssertCmd;
- if (QKeyValue.FindBoolAttribute(assertion.Attributes, "sourceloc")) {
- SourceLocationAttributes = assertion.Attributes;
- }
- }
-
- if (c is AssignCmd) {
- AssignCmd assign = c as AssignCmd;
-
- ReadCollector rc = new ReadCollector(NonLocalStateToCheck);
- foreach (var rhs in assign.Rhss)
- rc.Visit(rhs);
- if (rc.accesses.Count > 0) {
- foreach (AccessRecord ar in rc.accesses) {
- AddLogAndCheckCalls(result, ar, "READ");
- }
- }
-
- foreach (var lhs in assign.Lhss) {
- WriteCollector wc = new WriteCollector(NonLocalStateToCheck);
- wc.Visit(lhs);
- if (wc.GetAccess() != null) {
- AccessRecord ar = wc.GetAccess();
- AddLogAndCheckCalls(result, ar, "WRITE");
- }
- }
- }
- }
- return result;
- }
-
- private void AddLogAndCheckCalls(CmdSeq result, AccessRecord ar, string Access) {
- ExprSeq inParamsLog = new ExprSeq();
- ExprSeq inParamsChk = new ExprSeq();
- inParamsChk.Add(ar.Index);
- inParamsLog.Add(ar.Index);
- inParamsLog.Add(new LiteralExpr(Token.NoToken, BigNum.FromInt(CurrStmtNo), 32));
-
- Procedure logProcedure = GetRaceCheckingProcedure(Token.NoToken, "_LOG_" + Access + "_" + ar.v.Name);
- Procedure checkProcedure = GetRaceCheckingProcedure(Token.NoToken, "_CHECK_" + Access + "_" + ar.v.Name);
-
- verifier.OnlyThread1.Add(logProcedure.Name);
- verifier.OnlyThread2.Add(checkProcedure.Name);
-
- CallCmd logAccessCallCmd = new CallCmd(Token.NoToken, logProcedure.Name, inParamsLog, new IdentifierExprSeq());
- logAccessCallCmd.Proc = logProcedure;
-
- CallCmd checkAccessCallCmd = new CallCmd(Token.NoToken, checkProcedure.Name, inParamsChk, new IdentifierExprSeq());
- checkAccessCallCmd.Proc = checkProcedure;
- checkAccessCallCmd.Attributes = SourceLocationAttributes;
-
- result.Add(logAccessCallCmd);
- result.Add(checkAccessCallCmd);
-
- string fname = QKeyValue.FindStringAttribute(SourceLocationAttributes, "fname");
-
- string Key = ar.v.Name;
- if (Access == "WRITE")
- {
- if (!WriteAccessSourceLocations.ContainsKey(Key))
- {
- WriteAccessSourceLocations.Add(Key, new List<int>());
- }
- WriteAccessSourceLocations[Key].Add(CurrStmtNo);
- }
- else if (Access == "READ")
- {
- if (!ReadAccessSourceLocations.ContainsKey(Key))
- {
- ReadAccessSourceLocations.Add(Key, new List<int>());
- }
- ReadAccessSourceLocations[Key].Add(CurrStmtNo);
- }
-
- if (fname != null)
- {
- writeSourceLocToFile(SourceLocationAttributes, Path.GetFileNameWithoutExtension(CommandLineOptions.inputFiles[0]) + ".loc");
- }
- else
- {
- Debug.Assert(false, "RaceInstrumenter.AddLogAndCheckCalls: Could not write sourceloc to file as filename could not be found.\n");
- }
- CurrStmtNo++;
- }
-
- private BigBlock AddRaceCheckCalls(BigBlock bb) {
- BigBlock result = new BigBlock(bb.tok, bb.LabelName, AddRaceCheckCalls(bb.simpleCmds), null, bb.tc);
-
- if (bb.ec is WhileCmd) {
- WhileCmd WhileCommand = bb.ec as WhileCmd;
- result.ec = new WhileCmd(WhileCommand.tok, WhileCommand.Guard,
- WhileCommand.Invariants, AddRaceCheckCalls(WhileCommand.Body));
- }
- else if (bb.ec is IfCmd) {
- IfCmd IfCommand = bb.ec as IfCmd;
- Debug.Assert(IfCommand.elseIf == null); // We don't handle else if yet
- result.ec = new IfCmd(IfCommand.tok, IfCommand.Guard, AddRaceCheckCalls(IfCommand.thn), IfCommand.elseIf, IfCommand.elseBlock != null ? AddRaceCheckCalls(IfCommand.elseBlock) : null);
- }
- else if (bb.ec is BreakCmd) {
- result.ec = bb.ec;
- }
- else {
- Debug.Assert(bb.ec == null);
- }
-
- return result;
- }
-
- private Procedure GetRaceCheckingProcedure(IToken tok, string name) {
- if (RaceCheckingProcedures.ContainsKey(name)) {
- return RaceCheckingProcedures[name];
- }
- Procedure newProcedure = new Procedure(tok, name, new TypeVariableSeq(), new VariableSeq(), new VariableSeq(), new RequiresSeq(), new IdentifierExprSeq(), new EnsuresSeq());
- RaceCheckingProcedures[name] = newProcedure;
- return newProcedure;
- }
-
-
- public BigBlock MakeResetReadWriteSetStatements(Variable v, int Thread) {
- BigBlock result = new BigBlock(Token.NoToken, null, new CmdSeq(), null, null);
- if (Thread == 2) {
- return result;
- }
-
- Expr ResetReadAssumeGuard = Expr.Not(new IdentifierExpr(Token.NoToken,
- new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ"))));
- Expr ResetWriteAssumeGuard = Expr.Not(new IdentifierExpr(Token.NoToken,
- new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE"))));
-
- if (verifier.KernelArrayInfo.getGlobalArrays().Contains(v)) {
- ResetReadAssumeGuard = Expr.Imp(verifier.ThreadsInSameGroup(), ResetReadAssumeGuard);
- ResetWriteAssumeGuard = Expr.Imp(verifier.ThreadsInSameGroup(), ResetWriteAssumeGuard);
- }
-
- result.simpleCmds.Add(new AssumeCmd(Token.NoToken, ResetReadAssumeGuard));
- result.simpleCmds.Add(new AssumeCmd(Token.NoToken, ResetWriteAssumeGuard));
- return result;
- }
-
- protected Procedure MakeLogAccessProcedureHeader(Variable v, string ReadOrWrite) {
- VariableSeq inParams = new VariableSeq();
-
- Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool));
-
- Debug.Assert(v.TypedIdent.Type is MapType);
- MapType mt = v.TypedIdent.Type as MapType;
- Debug.Assert(mt.Arguments.Length == 1);
- Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0]));
- Variable SourceParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_source", mt.Arguments[0]));
- Debug.Assert(!(mt.Result is MapType));
-
- inParams.Add(new VariableDualiser(1, null, null).VisitVariable(PredicateParameter.Clone() as Variable));
- inParams.Add(new VariableDualiser(1, null, null).VisitVariable(OffsetParameter.Clone() as Variable));
- inParams.Add(new VariableDualiser(1, null, null).VisitVariable(SourceParameter.Clone() as Variable));
-
- string LogProcedureName = "_LOG_" + ReadOrWrite + "_" + v.Name;
-
- Procedure result = GetRaceCheckingProcedure(v.tok, LogProcedureName);
-
- result.InParams = inParams;
-
- result.AddAttribute("inline", new object[] { new LiteralExpr(v.tok, BigNum.FromInt(1)) });
-
- return result;
- }
-
- protected Procedure MakeCheckAccessProcedureHeader(Variable v, string ReadOrWrite) {
- VariableSeq inParams = new VariableSeq();
-
- Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool));
-
- Debug.Assert(v.TypedIdent.Type is MapType);
- MapType mt = v.TypedIdent.Type as MapType;
- Debug.Assert(mt.Arguments.Length == 1);
- Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0]));
- Debug.Assert(!(mt.Result is MapType));
-
- inParams.Add(new VariableDualiser(2, null, null).VisitVariable(PredicateParameter.Clone() as Variable));
- inParams.Add(new VariableDualiser(2, null, null).VisitVariable(OffsetParameter.Clone() as Variable));
-
- string CheckProcedureName = "_CHECK_" + ReadOrWrite + "_" + v.Name;
-
- Procedure result = GetRaceCheckingProcedure(v.tok, CheckProcedureName);
-
- result.InParams = inParams;
-
- result.AddAttribute("inline", new object[] { new LiteralExpr(v.tok, BigNum.FromInt(1)) });
-
- return result;
- }
-
- public void AddRaceCheckingCandidateRequires(Procedure Proc) {
- foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
- AddNoReadOrWriteCandidateRequires(Proc, v);
- AddReadOrWrittenOffsetIsThreadIdCandidateRequires(Proc, v);
- }
-
- DoHoudiniPointerAnalysis(Proc);
-
- }
-
- private void DoHoudiniPointerAnalysis(Procedure Proc) {
- HashSet<string> alreadyConsidered = new HashSet<string>();
-
- foreach (Variable v in Proc.InParams) {
- string strippedVarName = GPUVerifier.StripThreadIdentifier(v.Name);
- if (alreadyConsidered.Contains(strippedVarName)) {
- continue;
- }
- alreadyConsidered.Add(strippedVarName);
- if (v.TypedIdent.Type is CtorType) {
- CtorType ct = v.TypedIdent.Type as CtorType;
- if (ct.Decl.Name.Equals("ptr")) {
- foreach (var arrayCollection in new ICollection<Variable>[] {
- verifier.KernelArrayInfo.getGlobalArrays(), verifier.KernelArrayInfo.getGroupSharedArrays(),
- verifier.KernelArrayInfo.getPrivateArrays() }) {
- if (arrayCollection.Count == 0) {
- continue;
- }
-
- // This will need to be adapted to work with uniformity analysis
- foreach (string thread in new string[] { "1", "2" }) {
- Expr DisjunctionOverPointerSet = null;
- foreach (var array in arrayCollection) {
- Expr PointerSetDisjunct = Expr.Eq(MakePtrBaseExpr(v, strippedVarName, thread), MakeArrayIdExpr(array));
- DisjunctionOverPointerSet = (DisjunctionOverPointerSet == null ? PointerSetDisjunct : Expr.Or(DisjunctionOverPointerSet, PointerSetDisjunct));
- verifier.AddCandidateRequires(Proc,
- Expr.Imp(new IdentifierExpr(Token.NoToken, "_P$" + thread, Microsoft.Boogie.Type.Bool),
- Expr.Neq(MakePtrBaseExpr(v, strippedVarName, thread), MakeArrayIdExpr(array))));
- }
- Debug.Assert(DisjunctionOverPointerSet != null);
- verifier.AddCandidateRequires(Proc,
- Expr.Imp(new IdentifierExpr(Token.NoToken, "_P$" + thread, Microsoft.Boogie.Type.Bool),
- DisjunctionOverPointerSet));
- verifier.AddCandidateRequires(Proc,
- Expr.Imp(new IdentifierExpr(Token.NoToken, "_P$" + thread, Microsoft.Boogie.Type.Bool),
- Expr.Eq(MakePtrOffsetExpr(v, strippedVarName, thread), GPUVerifier.ZeroBV())));
- }
- }
- }
- }
- }
- }
-
- private static IdentifierExpr MakeArrayIdExpr(Variable array) {
- return new IdentifierExpr(Token.NoToken, "$arrayId" + array.Name, null);
- }
-
- private static NAryExpr MakePtrBaseExpr(Variable v, string strippedVarName, string thread) {
- return new NAryExpr(Token.NoToken, new FunctionCall(new IdentifierExpr(Token.NoToken, "base#MKPTR", v.TypedIdent.Type)),
- new ExprSeq(new Expr[] { new IdentifierExpr(Token.NoToken, strippedVarName + "$" + thread, v.TypedIdent.Type) }));
- }
-
- private static NAryExpr MakePtrOffsetExpr(Variable v, string strippedVarName, string thread) {
- return new NAryExpr(Token.NoToken, new FunctionCall(new IdentifierExpr(Token.NoToken, "offset#MKPTR", v.TypedIdent.Type)),
- new ExprSeq(new Expr[] { new IdentifierExpr(Token.NoToken, strippedVarName + "$" + thread, v.TypedIdent.Type) }));
- }
-
- public void AddRaceCheckingCandidateEnsures(Procedure Proc) {
- foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
- AddNoReadOrWriteCandidateEnsures(Proc, v);
- AddReadOrWrittenOffsetIsThreadIdCandidateEnsures(Proc, v);
- }
- }
-
- private void AddNoReadOrWriteCandidateRequires(Procedure Proc, Variable v, string ReadOrWrite, string OneOrTwo) {
- verifier.AddCandidateRequires(Proc, NoReadOrWriteExpr(v, ReadOrWrite, OneOrTwo));
- }
-
- private void AddNoReadOrWriteCandidateEnsures(Procedure Proc, Variable v, string ReadOrWrite, string OneOrTwo) {
- verifier.AddCandidateEnsures(Proc, NoReadOrWriteExpr(v, ReadOrWrite, OneOrTwo));
- }
-
- private HashSet<Expr> GetOffsetsAccessed(IRegion region, Variable v, string AccessType) {
- HashSet<Expr> result = new HashSet<Expr>();
-
- foreach (Cmd c in region.Cmds()) {
- if (c is CallCmd) {
- CallCmd call = c as CallCmd;
-
- if (call.callee == "_LOG_" + AccessType + "_" + v.Name) {
- // Ins[0] is thread 1's predicate,
- // Ins[1] is the offset to be read
- // If Ins[1] has the form BV32_ADD(offset#construct...(P), offset),
- // we are looking for the second parameter to this BV32_ADD
- Expr offset = call.Ins[1];
- if (offset is NAryExpr) {
- var nExpr = (NAryExpr)offset;
- if (nExpr.Fun.FunctionName == "BV32_ADD" &&
- nExpr.Args[0] is NAryExpr) {
- var n0Expr = (NAryExpr)nExpr.Args[0];
- if (n0Expr.Fun.FunctionName.StartsWith("offset#"))
- offset = nExpr.Args[1];
- }
- }
- result.Add(offset);
- }
-
- }
-
- }
-
- return result;
- }
-
- public void AddRaceCheckingDeclarations() {
- foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
- AddRaceCheckingDecsAndProcsForVar(v);
- }
- }
-
- protected void AddLogAccessProcedure(Variable v, string Access) {
- Procedure LogAccessProcedure = MakeLogAccessProcedureHeader(v, Access);
-
- Variable AccessHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, Access);
- Variable AccessOffsetXVariable = GPUVerifier.MakeOffsetVariable(v.Name, Access);
- Variable AccessSourceVariable = GPUVerifier.MakeSourceVariable(v.Name, Access);
-
- Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool));
-
- Debug.Assert(v.TypedIdent.Type is MapType);
- MapType mt = v.TypedIdent.Type as MapType;
- Debug.Assert(mt.Arguments.Length == 1);
- Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0]));
- Variable SourceParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_source", mt.Arguments[0]));
- Debug.Assert(!(mt.Result is MapType));
-
- VariableSeq locals = new VariableSeq();
- Variable TrackVariable = new LocalVariable(v.tok, new TypedIdent(v.tok, "track", Microsoft.Boogie.Type.Bool));
- locals.Add(TrackVariable);
-
- List<BigBlock> bigblocks = new List<BigBlock>();
-
- CmdSeq simpleCmds = new CmdSeq();
-
- simpleCmds.Add(new HavocCmd(v.tok, new IdentifierExprSeq(new IdentifierExpr[] { new IdentifierExpr(v.tok, TrackVariable) })));
-
- simpleCmds.Add(MakeConditionalAssignment(VariableForThread(1, AccessHasOccurredVariable),
- Expr.And(new IdentifierExpr(v.tok, VariableForThread(1, PredicateParameter)), new IdentifierExpr(v.tok, TrackVariable)), Expr.True));
- simpleCmds.Add(MakeConditionalAssignment(VariableForThread(1, AccessOffsetXVariable),
- Expr.And(new IdentifierExpr(v.tok, VariableForThread(1, PredicateParameter)), new IdentifierExpr(v.tok, TrackVariable)),
- new IdentifierExpr(v.tok, VariableForThread(1, OffsetParameter))));
- simpleCmds.Add(MakeConditionalAssignment(VariableForThread(1, AccessSourceVariable),
- Expr.And(new IdentifierExpr(v.tok, VariableForThread(1, PredicateParameter)), new IdentifierExpr(v.tok, TrackVariable)),
- new IdentifierExpr(v.tok, VariableForThread(1, SourceParameter))));
-
- bigblocks.Add(new BigBlock(v.tok, "_LOG_" + Access + "", simpleCmds, null, null));
-
- LogAccessProcedure.Modifies.Add(new IdentifierExpr(Token.NoToken, VariableForThread(1, AccessHasOccurredVariable)));
- LogAccessProcedure.Modifies.Add(new IdentifierExpr(Token.NoToken, VariableForThread(1, AccessOffsetXVariable)));
-
- Implementation LogAccessImplementation = new Implementation(v.tok, "_LOG_" + Access + "_" + v.Name, new TypeVariableSeq(), LogAccessProcedure.InParams, new VariableSeq(), locals, new StmtList(bigblocks, v.tok));
- LogAccessImplementation.AddAttribute("inline", new object[] { new LiteralExpr(v.tok, BigNum.FromInt(1)) });
-
- LogAccessImplementation.Proc = LogAccessProcedure;
-
- verifier.Program.TopLevelDeclarations.Add(LogAccessProcedure);
- verifier.Program.TopLevelDeclarations.Add(LogAccessImplementation);
- }
-
-
- protected void AddCheckAccessProcedure(Variable v, string Access) {
- Procedure CheckAccessProcedure = MakeCheckAccessProcedureHeader(v, Access);
-
- Variable AccessHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, Access);
- Variable AccessOffsetXVariable = GPUVerifier.MakeOffsetVariable(v.Name, Access);
-
- Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool));
-
- Debug.Assert(v.TypedIdent.Type is MapType);
- MapType mt = v.TypedIdent.Type as MapType;
- Debug.Assert(mt.Arguments.Length == 1);
- Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0]));
- Debug.Assert(!(mt.Result is MapType));
-
- if (Access.Equals("READ")) {
- // Check read by thread 2 does not conflict with write by thread 1
- Variable WriteHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE");
- Variable WriteOffsetVariable = GPUVerifier.MakeOffsetVariable(v.Name, "WRITE");
- Expr WriteReadGuard = new IdentifierExpr(Token.NoToken, VariableForThread(2, PredicateParameter));
- WriteReadGuard = Expr.And(WriteReadGuard, new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteHasOccurredVariable)));
- WriteReadGuard = Expr.And(WriteReadGuard, Expr.Eq(new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteOffsetVariable)),
- new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter))));
-
- if (!verifier.ArrayModelledAdversarially(v)) {
- WriteReadGuard = Expr.And(WriteReadGuard, Expr.Neq(
- MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteOffsetVariable)), 1, "WRITE"),
- MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter)), 2, "READ")
- ));
- }
-
- if (verifier.KernelArrayInfo.getGroupSharedArrays().Contains(v)) {
- WriteReadGuard = Expr.And(WriteReadGuard, verifier.ThreadsInSameGroup());
- }
-
- WriteReadGuard = Expr.Not(WriteReadGuard);
-
- Requires NoWriteReadRaceRequires = new Requires(false, WriteReadGuard);
- QKeyValue kv = new QKeyValue(Token.NoToken, "write_read", new List<object>(), null);
- NoWriteReadRaceRequires.Attributes = new QKeyValue(Token.NoToken, "race", new List<object>(), kv);
- CheckAccessProcedure.Requires.Add(NoWriteReadRaceRequires);
- }
- else {
- Debug.Assert(Access.Equals("WRITE"));
-
- // Check write by thread 2 does not conflict with write by thread 1
- Variable WriteHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE");
- Variable WriteOffsetVariable = GPUVerifier.MakeOffsetVariable(v.Name, "WRITE");
-
- Expr WriteWriteGuard = new IdentifierExpr(Token.NoToken, VariableForThread(2, PredicateParameter));
- WriteWriteGuard = Expr.And(WriteWriteGuard, new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteHasOccurredVariable)));
- WriteWriteGuard = Expr.And(WriteWriteGuard, Expr.Eq(new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteOffsetVariable)),
- new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter))));
- if (!verifier.ArrayModelledAdversarially(v)) {
- WriteWriteGuard = Expr.And(WriteWriteGuard, Expr.Neq(
- MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteOffsetVariable)), 1, "WRITE"),
- MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter)), 2, "WRITE")
- ));
- }
-
- if (verifier.KernelArrayInfo.getGroupSharedArrays().Contains(v)) {
- WriteWriteGuard = Expr.And(WriteWriteGuard, verifier.ThreadsInSameGroup());
- }
-
- WriteWriteGuard = Expr.Not(WriteWriteGuard);
- Requires NoWriteWriteRaceRequires = new Requires(false, WriteWriteGuard);
- QKeyValue kv = new QKeyValue(Token.NoToken, "write_write", new List<object>(), null);
- NoWriteWriteRaceRequires.Attributes = new QKeyValue(Token.NoToken, "race", new List<object>(), kv);
- CheckAccessProcedure.Requires.Add(NoWriteWriteRaceRequires);
-
- // Check write by thread 2 does not conflict with read by thread 1
- Variable ReadHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ");
- Variable ReadOffsetVariable = GPUVerifier.MakeOffsetVariable(v.Name, "READ");
-
- Expr ReadWriteGuard = new IdentifierExpr(Token.NoToken, VariableForThread(2, PredicateParameter));
- ReadWriteGuard = Expr.And(ReadWriteGuard, new IdentifierExpr(Token.NoToken, VariableForThread(1, ReadHasOccurredVariable)));
- ReadWriteGuard = Expr.And(ReadWriteGuard, Expr.Eq(new IdentifierExpr(Token.NoToken, VariableForThread(1, ReadOffsetVariable)),
- new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter))));
- if (!verifier.ArrayModelledAdversarially(v)) {
- ReadWriteGuard = Expr.And(ReadWriteGuard, Expr.Neq(
- MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, VariableForThread(1, ReadOffsetVariable)), 1, "WRITE"),
- MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter)), 2, "READ")
- ));
- }
-
- if (verifier.KernelArrayInfo.getGroupSharedArrays().Contains(v)) {
- ReadWriteGuard = Expr.And(ReadWriteGuard, verifier.ThreadsInSameGroup());
- }
-
- ReadWriteGuard = Expr.Not(ReadWriteGuard);
- Requires NoReadWriteRaceRequires = new Requires(false, ReadWriteGuard);
- kv = new QKeyValue(Token.NoToken, "read_write", new List<object>(), null);
- NoReadWriteRaceRequires.Attributes = new QKeyValue(Token.NoToken, "race", new List<object>(), kv);
- CheckAccessProcedure.Requires.Add(NoReadWriteRaceRequires);
-
- }
- verifier.Program.TopLevelDeclarations.Add(CheckAccessProcedure);
- }
-
-
-
- private Variable VariableForThread(int thread, Variable v) {
- return new VariableDualiser(thread, null, null).VisitVariable(v.Clone() as Variable);
- }
-
- protected void AddLogRaceDeclarations(Variable v, String ReadOrWrite) {
- verifier.FindOrCreateAccessHasOccurredVariable(v.Name, ReadOrWrite);
-
- Debug.Assert(v.TypedIdent.Type is MapType);
- MapType mt = v.TypedIdent.Type as MapType;
- Debug.Assert(mt.Arguments.Length == 1);
-
- verifier.FindOrCreateOffsetVariable(v.Name, ReadOrWrite);
- verifier.FindOrCreateSourceVariable(v.Name, ReadOrWrite);
-
- }
-
-
- private static AssignCmd MakeConditionalAssignment(Variable lhs, Expr condition, Expr rhs) {
- List<AssignLhs> lhss = new List<AssignLhs>();
- List<Expr> rhss = new List<Expr>();
- lhss.Add(new SimpleAssignLhs(lhs.tok, new IdentifierExpr(lhs.tok, lhs)));
- rhss.Add(new NAryExpr(rhs.tok, new IfThenElse(rhs.tok), new ExprSeq(new Expr[] { condition, rhs, new IdentifierExpr(lhs.tok, lhs) })));
- return new AssignCmd(lhs.tok, lhss, rhss);
- }
-
- private Expr MakeAccessedIndex(Variable v, Expr offsetExpr, int Thread, string AccessType) {
- Expr result = new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(v.Clone() as Variable));
- Debug.Assert(v.TypedIdent.Type is MapType);
- MapType mt = v.TypedIdent.Type as MapType;
- Debug.Assert(mt.Arguments.Length == 1);
-
- result = Expr.Select(result,
- new Expr[] { offsetExpr });
- Debug.Assert(!(mt.Result is MapType));
- return result;
- }
-
- protected void AddRequiresNoPendingAccess(Variable v) {
- IdentifierExpr ReadAccessOccurred1 = new IdentifierExpr(v.tok, new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ")));
- IdentifierExpr WriteAccessOccurred1 = new IdentifierExpr(v.tok, new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE")));
-
- verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.And(Expr.Not(ReadAccessOccurred1), Expr.Not(WriteAccessOccurred1))));
- }
-
- private void AddRequiresSourceAccessZero(Variable v)
- {
- verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(v.Name, "READ")),
- GPUVerifier.ZeroBV())));
- verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(v.Name, "WRITE")),
- GPUVerifier.ZeroBV())));
- }
-
- public void AddSourceLocationLoopInvariants(Implementation impl, IRegion region)
- {
- foreach (string key in WriteAccessSourceLocations.Keys.Union(ReadAccessSourceLocations.Keys))
- {
- region.AddInvariant(BuildNoAccessInvariant(key, "WRITE"));
- region.AddInvariant(BuildNoAccessInvariant(key, "READ"));
-
- if (WriteAccessSourceLocations.ContainsKey(key))
- {
- region.AddInvariant(BuildPossibleSourceLocationsInvariant(key, "WRITE"));
- }
- else
- {
- region.AddInvariant(BuildAccessOccurredFalseInvariant(key, "WRITE"));
- }
-
- if (ReadAccessSourceLocations.ContainsKey(key))
- {
- region.AddInvariant(BuildPossibleSourceLocationsInvariant(key, "READ"));
- }
- else
- {
- region.AddInvariant(BuildAccessOccurredFalseInvariant(key, "READ"));
- }
- }
- }
-
- private AssertCmd BuildAccessOccurredFalseInvariant(string name, string AccessType)
- {
- return new AssertCmd(Token.NoToken, Expr.Imp(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateAccessHasOccurredVariable(name, AccessType)),
- Expr.False));
- }
-
- private AssertCmd BuildNoAccessInvariant(string name, string AccessType)
- {
- return new AssertCmd(Token.NoToken, Expr.Imp(Expr.Not(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateAccessHasOccurredVariable(name, AccessType))),
- Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(name, AccessType)),
- new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 32))));
- }
-
- private AssertCmd BuildPossibleSourceLocationsInvariant(string name, string AccessType)
- {
- return new AssertCmd(Token.NoToken,
- Expr.Imp(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateAccessHasOccurredVariable(name, AccessType)),
- BuildDisjunctionFromAccessSourceLocations(name, AccessType)));
- }
-
- private Expr BuildDisjunctionFromAccessSourceLocations(string key, string AccessType)
- {
- Expr disj = Expr.False;
- Dictionary<string, List<int>> AccessSourceLocations = (AccessType.Equals("WRITE")) ? WriteAccessSourceLocations : ReadAccessSourceLocations;
- foreach (int loc in AccessSourceLocations[key])
- {
- if (disj.Equals(Expr.False))
- {
- disj = Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(key, AccessType)),
- new LiteralExpr(Token.NoToken, BigNum.FromInt(loc), 32));
- }
- else
- {
- disj = Expr.Or(disj, Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(key, AccessType)),
- new LiteralExpr(Token.NoToken, BigNum.FromInt(loc), 32)));
- }
- }
- return disj;
- }
-
- protected Expr NoReadOrWriteExpr(Variable v, string ReadOrWrite, string OneOrTwo) {
- Variable ReadOrWriteHasOccurred = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite);
- ReadOrWriteHasOccurred.Name = ReadOrWriteHasOccurred.Name + "$" + OneOrTwo;
- ReadOrWriteHasOccurred.TypedIdent.Name = ReadOrWriteHasOccurred.TypedIdent.Name + "$" + OneOrTwo;
- Expr expr = Expr.Not(new IdentifierExpr(v.tok, ReadOrWriteHasOccurred));
- return expr;
- }
-
-
- protected void AddOffsetsSatisfyPredicatesCandidateInvariant(IRegion region, Variable v, string ReadOrWrite, List<Expr> preds) {
- if (preds.Count != 0) {
- Expr expr = AccessedOffsetsSatisfyPredicatesExpr(v, preds, ReadOrWrite, 1);
- verifier.AddCandidateInvariant(region, expr, "accessed offsets satisfy predicates");
- }
- }
-
- private Expr AccessedOffsetsSatisfyPredicatesExpr(Variable v, IEnumerable<Expr> offsets, string ReadOrWrite, int Thread) {
- return Expr.Imp(
- new IdentifierExpr(Token.NoToken, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite))),
- offsets.Aggregate(Expr.Or));
- }
-
- private Expr AccessedOffsetIsThreadLocalIdExpr(Variable v, string ReadOrWrite, int Thread) {
- return Expr.Imp(
- new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite))),
- Expr.Eq(new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeOffsetVariable(v.Name, ReadOrWrite))), new IdentifierExpr(v.tok, verifier.MakeThreadId(v.tok, "X", Thread))));
- }
-
- private Expr GlobalIdExpr(string dimension, int Thread) {
- return new VariableDualiser(Thread, null, null).VisitExpr(verifier.GlobalIdExpr(dimension).Clone() as Expr);
- }
-
- protected void AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(IRegion region, Variable v, Expr constant, string ReadOrWrite) {
- Expr expr = MakeCTimesLocalIdRangeExpression(v, constant, ReadOrWrite, 1);
- verifier.AddCandidateInvariant(region,
- expr, "accessed offset in range [ C*local_id, (C+1)*local_id )");
- }
-
- private Expr MakeCTimesLocalIdRangeExpression(Variable v, Expr constant, string ReadOrWrite, int Thread) {
- Expr CTimesLocalId = verifier.MakeBVMul(constant.Clone() as Expr,
- new IdentifierExpr(Token.NoToken, verifier.MakeThreadId(Token.NoToken, "X", Thread)));
-
- Expr CTimesLocalIdPlusC = verifier.MakeBVAdd(verifier.MakeBVMul(constant.Clone() as Expr,
- new IdentifierExpr(Token.NoToken, verifier.MakeThreadId(Token.NoToken, "X", Thread))), constant.Clone() as Expr);
-
- Expr CTimesLocalIdLeqAccessedOffset = GPUVerifier.MakeBitVectorBinaryBoolean("BV32_LEQ", CTimesLocalId, OffsetXExpr(v, ReadOrWrite, Thread));
-
- Expr AccessedOffsetLtCTimesLocalIdPlusC = verifier.MakeBVSlt(OffsetXExpr(v, ReadOrWrite, Thread), CTimesLocalIdPlusC);
-
- return Expr.Imp(
- AccessHasOccurred(v, ReadOrWrite, Thread),
- Expr.And(CTimesLocalIdLeqAccessedOffset, AccessedOffsetLtCTimesLocalIdPlusC));
- }
-
- private static IdentifierExpr AccessHasOccurred(Variable v, string ReadOrWrite, int Thread) {
- return new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite)));
- }
-
- private static IdentifierExpr OffsetXExpr(Variable v, string ReadOrWrite, int Thread) {
- return new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeOffsetVariable(v.Name, ReadOrWrite)));
- }
-
- protected void AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(IRegion region, Variable v, Expr constant, string ReadOrWrite) {
- Expr expr = MakeCTimesGloalIdRangeExpr(v, constant, ReadOrWrite, 1);
- verifier.AddCandidateInvariant(region,
- expr, "accessed offset in range [ C*global_id, (C+1)*global_id )");
- }
-
- private Expr MakeCTimesGloalIdRangeExpr(Variable v, Expr constant, string ReadOrWrite, int Thread) {
- Expr CTimesGlobalId = verifier.MakeBVMul(constant.Clone() as Expr,
- GlobalIdExpr("X", Thread));
-
- Expr CTimesGlobalIdPlusC = verifier.MakeBVAdd(verifier.MakeBVMul(constant.Clone() as Expr,
- GlobalIdExpr("X", Thread)), constant.Clone() as Expr);
-
- Expr CTimesGlobalIdLeqAccessedOffset = GPUVerifier.MakeBitVectorBinaryBoolean("BV32_LEQ", CTimesGlobalId, OffsetXExpr(v, ReadOrWrite, Thread));
-
- Expr AccessedOffsetLtCTimesGlobalIdPlusC = verifier.MakeBVSlt(OffsetXExpr(v, ReadOrWrite, Thread), CTimesGlobalIdPlusC);
-
- Expr implication = Expr.Imp(
- AccessHasOccurred(v, ReadOrWrite, Thread),
- Expr.And(CTimesGlobalIdLeqAccessedOffset, AccessedOffsetLtCTimesGlobalIdPlusC));
- return implication;
- }
-
- private void writeSourceLocToFile(QKeyValue kv, string path) {
- TextWriter tw = new StreamWriter(path, true);
- tw.Write("\n" + QKeyValue.FindIntAttribute(SourceLocationAttributes, "line", -1)
- + "#" + QKeyValue.FindIntAttribute(SourceLocationAttributes, "col", -1)
- + "#" + QKeyValue.FindStringAttribute(SourceLocationAttributes, "fname")
- + "#" + QKeyValue.FindStringAttribute(SourceLocationAttributes, "dir"));
- tw.Close();
- }
-
- protected void AddAccessedOffsetIsThreadLocalIdCandidateRequires(Procedure Proc, Variable v, string ReadOrWrite, int Thread) {
- verifier.AddCandidateRequires(Proc, AccessedOffsetIsThreadLocalIdExpr(v, ReadOrWrite, Thread));
- }
-
- protected void AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Procedure Proc, Variable v, string ReadOrWrite, int Thread) {
- verifier.AddCandidateEnsures(Proc, AccessedOffsetIsThreadLocalIdExpr(v, ReadOrWrite, Thread));
- }
-
-
-
- }
-
-
-
- class FindReferencesToNamedVariableVisitor : StandardVisitor {
- internal bool found = false;
- private string name;
-
- internal FindReferencesToNamedVariableVisitor(string name) {
- this.name = name;
- }
-
- public override Variable VisitVariable(Variable node) {
- if (GPUVerifier.StripThreadIdentifier(node.Name).Equals(name)) {
- found = true;
- }
- return base.VisitVariable(node);
- }
- }
-
-
-
-}
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie;
+using Microsoft.Basetypes;
+
+namespace GPUVerify {
+ class RaceInstrumenter : IRaceInstrumenter {
+ protected GPUVerifier verifier;
+
+ private QKeyValue SourceLocationAttributes = null;
+
+ private int CurrStmtNo = 1;
+
+ private Dictionary<string, List<int>> ReadAccessSourceLocations = new Dictionary<string, List<int>>();
+
+ private Dictionary<string, List<int>> WriteAccessSourceLocations = new Dictionary<string, List<int>>();
+
+ public IKernelArrayInfo NonLocalStateToCheck;
+
+ private Dictionary<string, Procedure> RaceCheckingProcedures = new Dictionary<string, Procedure>();
+
+ public void setVerifier(GPUVerifier verifier) {
+ this.verifier = verifier;
+ NonLocalStateToCheck = new KernelArrayInfoLists();
+ foreach (Variable v in verifier.KernelArrayInfo.getGlobalArrays()) {
+ NonLocalStateToCheck.getGlobalArrays().Add(v);
+ }
+ foreach (Variable v in verifier.KernelArrayInfo.getGroupSharedArrays()) {
+ NonLocalStateToCheck.getGroupSharedArrays().Add(v);
+ }
+ }
+
+ private void AddNoReadOrWriteCandidateInvariants(IRegion region, Variable v) {
+ // Reasoning: if READ_HAS_OCCURRED_v is not in the modifies set for the
+ // loop then there is no point adding an invariant
+ //
+ // If READ_HAS_OCCURRED_v is in the modifies set, but the loop does not
+ // contain a barrier, then it is almost certain that a read CAN be
+ // pending at the loop head, so the invariant will not hold
+ //
+ // If there is a barrier in the loop body then READ_HAS_OCCURRED_v will
+ // be in the modifies set, but there may not be a live read at the loop
+ // head, so it is worth adding the loop invariant candidate.
+ //
+ // The same reasoning applies for WRITE
+
+ if (verifier.ContainsBarrierCall(region)) {
+ if (verifier.ContainsNamedVariable(
+ LoopInvariantGenerator.GetModifiedVariables(region), GPUVerifier.MakeAccessHasOccurredVariableName(v.Name, "READ"))) {
+ AddNoReadOrWriteCandidateInvariant(region, v, "READ");
+ }
+
+ if (verifier.ContainsNamedVariable(
+ LoopInvariantGenerator.GetModifiedVariables(region), GPUVerifier.MakeAccessHasOccurredVariableName(v.Name, "WRITE"))) {
+ AddNoReadOrWriteCandidateInvariant(region, v, "WRITE");
+ }
+ }
+ }
+
+ private void AddNoReadOrWriteCandidateRequires(Procedure Proc, Variable v) {
+ AddNoReadOrWriteCandidateRequires(Proc, v, "READ", "1");
+ AddNoReadOrWriteCandidateRequires(Proc, v, "WRITE", "1");
+ }
+
+ private void AddNoReadOrWriteCandidateEnsures(Procedure Proc, Variable v) {
+ AddNoReadOrWriteCandidateEnsures(Proc, v, "READ", "1");
+ AddNoReadOrWriteCandidateEnsures(Proc, v, "WRITE", "1");
+ }
+
+ private void AddNoReadOrWriteCandidateInvariant(IRegion region, Variable v, string ReadOrWrite) {
+ Expr candidate = NoReadOrWriteExpr(v, ReadOrWrite, "1");
+ verifier.AddCandidateInvariant(region, candidate, "no " + ReadOrWrite.ToLower());
+ }
+
+ public void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region) {
+ List<Expr> offsetPredicatesRead = new List<Expr>();
+ List<Expr> offsetPredicatesWrite = new List<Expr>();
+ foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
+ AddNoReadOrWriteCandidateInvariants(region, v);
+ AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(impl, region, v, "READ");
+ AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(impl, region, v, "WRITE");
+ offsetPredicatesRead = CollectOffsetPredicates(impl, region, v, "READ");
+ offsetPredicatesWrite = CollectOffsetPredicates(impl, region, v, "WRITE");
+ AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "READ", offsetPredicatesRead);
+ AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "WRITE", offsetPredicatesWrite);
+ AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "READ", new List<Expr>(offsetPredicatesRead.Zip(CollectSourceLocPredicates(region, v, "READ"), Expr.And)));
+ AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "WRITE", new List<Expr>(offsetPredicatesWrite.Zip(CollectSourceLocPredicates(region, v, "WRITE"), Expr.And)));
+ }
+ }
+
+ private void AddAccessRelatedCandidateInvariant(IRegion region, string accessKind, Expr candidateInvariantExpr, string procName, string tag) {
+ Expr candidate = new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(candidateInvariantExpr.Clone() as Expr);
+ verifier.AddCandidateInvariant(region, candidate, tag);
+ }
+
+ private bool DoesNotReferTo(Expr expr, string v) {
+ FindReferencesToNamedVariableVisitor visitor = new FindReferencesToNamedVariableVisitor(v);
+ visitor.VisitExpr(expr);
+ return !visitor.found;
+ }
+
+ private List<Expr> CollectSourceLocPredicates(IRegion region, Variable v, string accessType) {
+ var sourceVar = verifier.FindOrCreateSourceVariable(v.Name, accessType);
+ var sourceExpr = new IdentifierExpr(Token.NoToken, sourceVar);
+ var sourcePreds = new List<Expr>();
+
+ foreach (Cmd c in region.Cmds()) {
+ if (c is CallCmd) {
+ CallCmd call = c as CallCmd;
+ if (call.callee == "_LOG_" + accessType + "_" + v.Name) {
+ sourcePreds.Add(Expr.Eq(sourceExpr, call.Ins[2]));
+ }
+ }
+ }
+
+ return sourcePreds;
+ }
+ private List<Expr> CollectOffsetPredicates(Implementation impl, IRegion region, Variable v, string accessType) {
+ var offsetVar = new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeOffsetVariable(v.Name, accessType));
+ var offsetExpr = new IdentifierExpr(Token.NoToken, offsetVar);
+ var offsetPreds = new List<Expr>();
+
+ foreach (var offset in GetOffsetsAccessed(region, v, accessType)) {
+ bool isConstant;
+ var def = verifier.varDefAnalyses[impl].SubstDefinitions(offset, impl.Name, out isConstant);
+ if (def == null)
+ continue;
+
+ if (isConstant) {
+ offsetPreds.Add(Expr.Eq(offsetExpr, def));
+ }
+ else {
+ var sc = StrideConstraint.FromExpr(verifier, impl, def);
+ var pred = sc.MaybeBuildPredicate(verifier, offsetExpr);
+ if (pred != null)
+ offsetPreds.Add(pred);
+ }
+ }
+
+ return offsetPreds;
+ }
+
+ private void AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(Implementation impl, IRegion region, Variable v, string accessType) {
+ KeyValuePair<IdentifierExpr, Expr> iLessThanC = GetILessThanC(region.Guard());
+ if (iLessThanC.Key != null) {
+ foreach (Expr e in GetOffsetsAccessed(region, v, accessType)) {
+ if (HasFormIPlusLocalIdTimesC(e, iLessThanC, impl)) {
+ AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(region, v, iLessThanC.Value, accessType);
+ break;
+ }
+ }
+
+ foreach (Expr e in GetOffsetsAccessed(region, v, accessType)) {
+ if (HasFormIPlusGlobalIdTimesC(e, iLessThanC, impl)) {
+ AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(region, v, iLessThanC.Value, accessType);
+ break;
+ }
+ }
+
+ }
+
+
+ }
+
+ private bool HasFormIPlusLocalIdTimesC(Expr e, KeyValuePair<IdentifierExpr, Expr> iLessThanC, Implementation impl) {
+ if (!(e is NAryExpr)) {
+ return false;
+ }
+
+ NAryExpr nary = e as NAryExpr;
+
+ if (!nary.Fun.FunctionName.Equals("BV32_ADD")) {
+ return false;
+ }
+
+ return (SameIdentifierExpression(nary.Args[0], iLessThanC.Key) &&
+ IsLocalIdTimesConstant(nary.Args[1], iLessThanC.Value, impl)) ||
+ (SameIdentifierExpression(nary.Args[1], iLessThanC.Key) &&
+ IsLocalIdTimesConstant(nary.Args[0], iLessThanC.Value, impl));
+ }
+
+ private bool IsLocalIdTimesConstant(Expr maybeLocalIdTimesConstant, Expr constant, Implementation impl) {
+ if (!(maybeLocalIdTimesConstant is NAryExpr)) {
+ return false;
+ }
+ NAryExpr nary = maybeLocalIdTimesConstant as NAryExpr;
+ if (!nary.Fun.FunctionName.Equals("BV32_MUL")) {
+ return false;
+ }
+
+ return
+ (SameConstant(nary.Args[0], constant) && verifier.IsLocalId(nary.Args[1], 0, impl)) ||
+ (SameConstant(nary.Args[1], constant) && verifier.IsLocalId(nary.Args[0], 0, impl));
+ }
+
+
+ private bool HasFormIPlusGlobalIdTimesC(Expr e, KeyValuePair<IdentifierExpr, Expr> iLessThanC, Implementation impl) {
+ if (!(e is NAryExpr)) {
+ return false;
+ }
+
+ NAryExpr nary = e as NAryExpr;
+
+ if (!nary.Fun.FunctionName.Equals("BV32_ADD")) {
+ return false;
+ }
+
+ return (SameIdentifierExpression(nary.Args[0], iLessThanC.Key) &&
+ IsGlobalIdTimesConstant(nary.Args[1], iLessThanC.Value, impl)) ||
+ (SameIdentifierExpression(nary.Args[1], iLessThanC.Key) &&
+ IsGlobalIdTimesConstant(nary.Args[0], iLessThanC.Value, impl));
+ }
+
+ private bool IsGlobalIdTimesConstant(Expr maybeGlobalIdTimesConstant, Expr constant, Implementation impl) {
+ if (!(maybeGlobalIdTimesConstant is NAryExpr)) {
+ return false;
+ }
+ NAryExpr nary = maybeGlobalIdTimesConstant as NAryExpr;
+ if (!nary.Fun.FunctionName.Equals("BV32_MUL")) {
+ return false;
+ }
+
+ return
+ (SameConstant(nary.Args[0], constant) && verifier.IsGlobalId(nary.Args[1], 0, impl)) ||
+ (SameConstant(nary.Args[1], constant) && verifier.IsGlobalId(nary.Args[0], 0, impl));
+ }
+
+
+ private bool SameConstant(Expr expr, Expr constant) {
+ if (constant is IdentifierExpr) {
+ IdentifierExpr identifierExpr = constant as IdentifierExpr;
+ Debug.Assert(identifierExpr.Decl is Constant);
+ return expr is IdentifierExpr && (expr as IdentifierExpr).Decl is Constant && (expr as IdentifierExpr).Decl.Name.Equals(identifierExpr.Decl.Name);
+ }
+ else {
+ Debug.Assert(constant is LiteralExpr);
+ LiteralExpr literalExpr = constant as LiteralExpr;
+ if (!(expr is LiteralExpr)) {
+ return false;
+ }
+ if (!(literalExpr.Val is BvConst) || !((expr as LiteralExpr).Val is BvConst)) {
+ return false;
+ }
+
+ return (literalExpr.Val as BvConst).Value.ToInt == ((expr as LiteralExpr).Val as BvConst).Value.ToInt;
+ }
+ }
+
+ private bool SameIdentifierExpression(Expr expr, IdentifierExpr identifierExpr) {
+ if (!(expr is IdentifierExpr)) {
+ return false;
+ }
+ return (expr as IdentifierExpr).Decl.Name.Equals(identifierExpr.Name);
+ }
+
+ private KeyValuePair<IdentifierExpr, Expr> GetILessThanC(Expr expr) {
+
+ if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("bv32_to_bool")) {
+ expr = (expr as NAryExpr).Args[0];
+ }
+
+ if (!(expr is NAryExpr)) {
+ return new KeyValuePair<IdentifierExpr, Expr>(null, null);
+ }
+
+ NAryExpr nary = expr as NAryExpr;
+
+ if (!(nary.Fun.FunctionName.Equals("BV32_C_LT") || nary.Fun.FunctionName.Equals("BV32_LT"))) {
+ return new KeyValuePair<IdentifierExpr, Expr>(null, null);
+ }
+
+ if (!(nary.Args[0] is IdentifierExpr)) {
+ return new KeyValuePair<IdentifierExpr, Expr>(null, null);
+ }
+
+ if (!IsConstant(nary.Args[1])) {
+ return new KeyValuePair<IdentifierExpr, Expr>(null, null);
+ }
+
+ return new KeyValuePair<IdentifierExpr, Expr>(nary.Args[0] as IdentifierExpr, nary.Args[1]);
+
+ }
+
+ private static bool IsConstant(Expr e) {
+ return ((e is IdentifierExpr && (e as IdentifierExpr).Decl is Constant) || e is LiteralExpr);
+ }
+
+ private void AddReadOrWrittenOffsetIsThreadIdCandidateRequires(Procedure Proc, Variable v) {
+ AddAccessedOffsetIsThreadLocalIdCandidateRequires(Proc, v, "WRITE", 1);
+ AddAccessedOffsetIsThreadLocalIdCandidateRequires(Proc, v, "READ", 1);
+ }
+
+ private void AddReadOrWrittenOffsetIsThreadIdCandidateEnsures(Procedure Proc, Variable v) {
+ AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Proc, v, "WRITE", 1);
+ AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Proc, v, "READ", 1);
+ }
+
+ public void AddKernelPrecondition() {
+ foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
+ AddRequiresNoPendingAccess(v);
+ AddRequiresSourceAccessZero(v);
+ }
+ }
+
+ public void AddRaceCheckingInstrumentation() {
+
+ foreach (Declaration d in verifier.Program.TopLevelDeclarations) {
+ if (d is Implementation) {
+ AddRaceCheckCalls(d as Implementation);
+ }
+ }
+
+ }
+
+ private void AddRaceCheckingDecsAndProcsForVar(Variable v) {
+ AddLogRaceDeclarations(v, "READ");
+ AddLogRaceDeclarations(v, "WRITE");
+ AddLogAccessProcedure(v, "READ");
+ AddCheckAccessProcedure(v, "READ");
+ AddLogAccessProcedure(v, "WRITE");
+ AddCheckAccessProcedure(v, "WRITE");
+ }
+
+ private StmtList AddRaceCheckCalls(StmtList stmtList) {
+ Contract.Requires(stmtList != null);
+
+ StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
+
+ foreach (BigBlock bodyBlock in stmtList.BigBlocks) {
+ result.BigBlocks.Add(AddRaceCheckCalls(bodyBlock));
+ }
+ return result;
+ }
+
+ private Block AddRaceCheckCalls(Block b) {
+ b.Cmds = AddRaceCheckCalls(b.Cmds);
+ return b;
+ }
+
+ private void AddRaceCheckCalls(Implementation impl) {
+ if (CommandLineOptions.Unstructured)
+ impl.Blocks = impl.Blocks.Select(AddRaceCheckCalls).ToList();
+ else
+ impl.StructuredStmts = AddRaceCheckCalls(impl.StructuredStmts);
+ }
+
+ private CmdSeq AddRaceCheckCalls(CmdSeq cs) {
+ var result = new CmdSeq();
+ foreach (Cmd c in cs) {
+ result.Add(c);
+
+ if (c is AssertCmd) {
+ AssertCmd assertion = c as AssertCmd;
+ if (QKeyValue.FindBoolAttribute(assertion.Attributes, "sourceloc")) {
+ SourceLocationAttributes = assertion.Attributes;
+ }
+ }
+
+ if (c is AssignCmd) {
+ AssignCmd assign = c as AssignCmd;
+
+ ReadCollector rc = new ReadCollector(NonLocalStateToCheck);
+ foreach (var rhs in assign.Rhss)
+ rc.Visit(rhs);
+ if (rc.accesses.Count > 0) {
+ foreach (AccessRecord ar in rc.accesses) {
+ AddLogAndCheckCalls(result, ar, "READ");
+ }
+ }
+
+ foreach (var lhs in assign.Lhss) {
+ WriteCollector wc = new WriteCollector(NonLocalStateToCheck);
+ wc.Visit(lhs);
+ if (wc.GetAccess() != null) {
+ AccessRecord ar = wc.GetAccess();
+ AddLogAndCheckCalls(result, ar, "WRITE");
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ private void AddLogAndCheckCalls(CmdSeq result, AccessRecord ar, string Access) {
+ ExprSeq inParamsLog = new ExprSeq();
+ ExprSeq inParamsChk = new ExprSeq();
+ inParamsChk.Add(ar.Index);
+ inParamsLog.Add(ar.Index);
+ inParamsLog.Add(new LiteralExpr(Token.NoToken, BigNum.FromInt(CurrStmtNo), 32));
+
+ Procedure logProcedure = GetRaceCheckingProcedure(Token.NoToken, "_LOG_" + Access + "_" + ar.v.Name);
+ Procedure checkProcedure = GetRaceCheckingProcedure(Token.NoToken, "_CHECK_" + Access + "_" + ar.v.Name);
+
+ verifier.OnlyThread1.Add(logProcedure.Name);
+ verifier.OnlyThread2.Add(checkProcedure.Name);
+
+ CallCmd logAccessCallCmd = new CallCmd(Token.NoToken, logProcedure.Name, inParamsLog, new IdentifierExprSeq());
+ logAccessCallCmd.Proc = logProcedure;
+
+ CallCmd checkAccessCallCmd = new CallCmd(Token.NoToken, checkProcedure.Name, inParamsChk, new IdentifierExprSeq());
+ checkAccessCallCmd.Proc = checkProcedure;
+ checkAccessCallCmd.Attributes = SourceLocationAttributes;
+
+ result.Add(logAccessCallCmd);
+ result.Add(checkAccessCallCmd);
+
+ string fname = QKeyValue.FindStringAttribute(SourceLocationAttributes, "fname");
+
+ string Key = ar.v.Name;
+ if (Access == "WRITE")
+ {
+ if (!WriteAccessSourceLocations.ContainsKey(Key))
+ {
+ WriteAccessSourceLocations.Add(Key, new List<int>());
+ }
+ WriteAccessSourceLocations[Key].Add(CurrStmtNo);
+ }
+ else if (Access == "READ")
+ {
+ if (!ReadAccessSourceLocations.ContainsKey(Key))
+ {
+ ReadAccessSourceLocations.Add(Key, new List<int>());
+ }
+ ReadAccessSourceLocations[Key].Add(CurrStmtNo);
+ }
+
+ if (fname != null)
+ {
+ writeSourceLocToFile(SourceLocationAttributes, Path.GetFileNameWithoutExtension(CommandLineOptions.inputFiles[0]) + ".loc");
+ }
+ else
+ {
+ Debug.Assert(false, "RaceInstrumenter.AddLogAndCheckCalls: Could not write sourceloc to file as filename could not be found.\n");
+ }
+ CurrStmtNo++;
+ }
+
+ private BigBlock AddRaceCheckCalls(BigBlock bb) {
+ BigBlock result = new BigBlock(bb.tok, bb.LabelName, AddRaceCheckCalls(bb.simpleCmds), null, bb.tc);
+
+ if (bb.ec is WhileCmd) {
+ WhileCmd WhileCommand = bb.ec as WhileCmd;
+ result.ec = new WhileCmd(WhileCommand.tok, WhileCommand.Guard,
+ WhileCommand.Invariants, AddRaceCheckCalls(WhileCommand.Body));
+ }
+ else if (bb.ec is IfCmd) {
+ IfCmd IfCommand = bb.ec as IfCmd;
+ Debug.Assert(IfCommand.elseIf == null); // We don't handle else if yet
+ result.ec = new IfCmd(IfCommand.tok, IfCommand.Guard, AddRaceCheckCalls(IfCommand.thn), IfCommand.elseIf, IfCommand.elseBlock != null ? AddRaceCheckCalls(IfCommand.elseBlock) : null);
+ }
+ else if (bb.ec is BreakCmd) {
+ result.ec = bb.ec;
+ }
+ else {
+ Debug.Assert(bb.ec == null);
+ }
+
+ return result;
+ }
+
+ private Procedure GetRaceCheckingProcedure(IToken tok, string name) {
+ if (RaceCheckingProcedures.ContainsKey(name)) {
+ return RaceCheckingProcedures[name];
+ }
+ Procedure newProcedure = new Procedure(tok, name, new TypeVariableSeq(), new VariableSeq(), new VariableSeq(), new RequiresSeq(), new IdentifierExprSeq(), new EnsuresSeq());
+ RaceCheckingProcedures[name] = newProcedure;
+ return newProcedure;
+ }
+
+
+ public BigBlock MakeResetReadWriteSetStatements(Variable v, Expr ResetCondition) {
+ BigBlock result = new BigBlock(Token.NoToken, null, new CmdSeq(), null, null);
+
+ Expr ResetReadAssumeGuard = Expr.Imp(ResetCondition,
+ Expr.Not(new IdentifierExpr(Token.NoToken,
+ new VariableDualiser(1, null, null).VisitVariable(
+ GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ")))));
+ Expr ResetWriteAssumeGuard = Expr.Imp(ResetCondition,
+ Expr.Not(new IdentifierExpr(Token.NoToken,
+ new VariableDualiser(1, null, null).VisitVariable(
+ GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE")))));
+
+ if (verifier.KernelArrayInfo.getGlobalArrays().Contains(v)) {
+ ResetReadAssumeGuard = Expr.Imp(GPUVerifier.ThreadsInSameGroup(), ResetReadAssumeGuard);
+ ResetWriteAssumeGuard = Expr.Imp(GPUVerifier.ThreadsInSameGroup(), ResetWriteAssumeGuard);
+ }
+
+ result.simpleCmds.Add(new AssumeCmd(Token.NoToken, ResetReadAssumeGuard));
+ result.simpleCmds.Add(new AssumeCmd(Token.NoToken, ResetWriteAssumeGuard));
+ return result;
+ }
+
+ protected Procedure MakeLogAccessProcedureHeader(Variable v, string ReadOrWrite) {
+ VariableSeq inParams = new VariableSeq();
+
+ Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool));
+
+ Debug.Assert(v.TypedIdent.Type is MapType);
+ MapType mt = v.TypedIdent.Type as MapType;
+ Debug.Assert(mt.Arguments.Length == 1);
+ Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0]));
+ Variable SourceParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_source", mt.Arguments[0]));
+ Debug.Assert(!(mt.Result is MapType));
+
+ inParams.Add(new VariableDualiser(1, null, null).VisitVariable(PredicateParameter.Clone() as Variable));
+ inParams.Add(new VariableDualiser(1, null, null).VisitVariable(OffsetParameter.Clone() as Variable));
+ inParams.Add(new VariableDualiser(1, null, null).VisitVariable(SourceParameter.Clone() as Variable));
+
+ string LogProcedureName = "_LOG_" + ReadOrWrite + "_" + v.Name;
+
+ Procedure result = GetRaceCheckingProcedure(v.tok, LogProcedureName);
+
+ result.InParams = inParams;
+
+ result.AddAttribute("inline", new object[] { new LiteralExpr(v.tok, BigNum.FromInt(1)) });
+
+ return result;
+ }
+
+ protected Procedure MakeCheckAccessProcedureHeader(Variable v, string ReadOrWrite) {
+ VariableSeq inParams = new VariableSeq();
+
+ Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool));
+
+ Debug.Assert(v.TypedIdent.Type is MapType);
+ MapType mt = v.TypedIdent.Type as MapType;
+ Debug.Assert(mt.Arguments.Length == 1);
+ Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0]));
+ Debug.Assert(!(mt.Result is MapType));
+
+ inParams.Add(new VariableDualiser(2, null, null).VisitVariable(PredicateParameter.Clone() as Variable));
+ inParams.Add(new VariableDualiser(2, null, null).VisitVariable(OffsetParameter.Clone() as Variable));
+
+ string CheckProcedureName = "_CHECK_" + ReadOrWrite + "_" + v.Name;
+
+ Procedure result = GetRaceCheckingProcedure(v.tok, CheckProcedureName);
+
+ result.InParams = inParams;
+
+ result.AddAttribute("inline", new object[] { new LiteralExpr(v.tok, BigNum.FromInt(1)) });
+
+ return result;
+ }
+
+ public void AddRaceCheckingCandidateRequires(Procedure Proc) {
+ foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
+ AddNoReadOrWriteCandidateRequires(Proc, v);
+ AddReadOrWrittenOffsetIsThreadIdCandidateRequires(Proc, v);
+ }
+ }
+
+ public void DoHoudiniPointerAnalysis(Procedure Proc) {
+ foreach (Variable v in Proc.InParams) {
+ if (v.TypedIdent.Type is CtorType) {
+ CtorType ct = v.TypedIdent.Type as CtorType;
+ if (ct.Decl.Name.Equals("ptr")) {
+ foreach (var arrayCollection in new ICollection<Variable>[] {
+ verifier.KernelArrayInfo.getGlobalArrays(), verifier.KernelArrayInfo.getGroupSharedArrays(),
+ verifier.KernelArrayInfo.getPrivateArrays() }) {
+ if (arrayCollection.Count == 0) {
+ continue;
+ }
+
+ Expr DisjunctionOverPointerSet = null;
+ foreach (var array in arrayCollection) {
+ Expr PointerSetDisjunct = Expr.Eq(MakePtrBaseExpr(v), MakeArrayIdExpr(array));
+ DisjunctionOverPointerSet = (DisjunctionOverPointerSet == null ? PointerSetDisjunct : Expr.Or(DisjunctionOverPointerSet, PointerSetDisjunct));
+ verifier.AddCandidateRequires(Proc,
+ Expr.Neq(MakePtrBaseExpr(v), MakeArrayIdExpr(array)));
+ }
+ Debug.Assert(DisjunctionOverPointerSet != null);
+ verifier.AddCandidateRequires(Proc, DisjunctionOverPointerSet);
+ verifier.AddCandidateRequires(Proc, Expr.Eq(MakePtrOffsetExpr(v), GPUVerifier.ZeroBV()));
+ }
+ }
+ }
+ }
+ }
+
+ private IdentifierExpr MakeArrayIdExpr(Variable array) {
+ var arrayId = verifier.ResContext.LookUpVariable("$arrayId" + array.Name);
+ return new IdentifierExpr(Token.NoToken, arrayId);
+ }
+
+ private NAryExpr MakePtrBaseExpr(Variable v) {
+ var baseSel = (Function)verifier.ResContext.LookUpProcedure("base#MKPTR");
+ return new NAryExpr(Token.NoToken, new FunctionCall(baseSel),
+ new ExprSeq(new Expr[] { Expr.Ident(v) }));
+ }
+
+ private NAryExpr MakePtrOffsetExpr(Variable v) {
+ var offsetSel = (Function)verifier.ResContext.LookUpProcedure("offset#MKPTR");
+ return new NAryExpr(Token.NoToken, new FunctionCall(offsetSel),
+ new ExprSeq(new Expr[] { Expr.Ident(v) }));
+ }
+
+ public void AddRaceCheckingCandidateEnsures(Procedure Proc) {
+ foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
+ AddNoReadOrWriteCandidateEnsures(Proc, v);
+ AddReadOrWrittenOffsetIsThreadIdCandidateEnsures(Proc, v);
+ }
+ }
+
+ private void AddNoReadOrWriteCandidateRequires(Procedure Proc, Variable v, string ReadOrWrite, string OneOrTwo) {
+ verifier.AddCandidateRequires(Proc, NoReadOrWriteExpr(v, ReadOrWrite, OneOrTwo));
+ }
+
+ private void AddNoReadOrWriteCandidateEnsures(Procedure Proc, Variable v, string ReadOrWrite, string OneOrTwo) {
+ verifier.AddCandidateEnsures(Proc, NoReadOrWriteExpr(v, ReadOrWrite, OneOrTwo));
+ }
+
+ private HashSet<Expr> GetOffsetsAccessed(IRegion region, Variable v, string AccessType) {
+ HashSet<Expr> result = new HashSet<Expr>();
+
+ foreach (Cmd c in region.Cmds()) {
+ if (c is CallCmd) {
+ CallCmd call = c as CallCmd;
+
+ if (call.callee == "_LOG_" + AccessType + "_" + v.Name) {
+ // Ins[0] is thread 1's predicate,
+ // Ins[1] is the offset to be read
+ // If Ins[1] has the form BV32_ADD(offset#construct...(P), offset),
+ // we are looking for the second parameter to this BV32_ADD
+ Expr offset = call.Ins[1];
+ if (offset is NAryExpr) {
+ var nExpr = (NAryExpr)offset;
+ if (nExpr.Fun.FunctionName == "BV32_ADD" &&
+ nExpr.Args[0] is NAryExpr) {
+ var n0Expr = (NAryExpr)nExpr.Args[0];
+ if (n0Expr.Fun.FunctionName.StartsWith("offset#"))
+ offset = nExpr.Args[1];
+ }
+ }
+ result.Add(offset);
+ }
+
+ }
+
+ }
+
+ return result;
+ }
+
+ public void AddRaceCheckingDeclarations() {
+ foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
+ AddRaceCheckingDecsAndProcsForVar(v);
+ }
+ }
+
+ protected void AddLogAccessProcedure(Variable v, string Access) {
+ Procedure LogAccessProcedure = MakeLogAccessProcedureHeader(v, Access);
+
+ Variable AccessHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, Access);
+ Variable AccessOffsetXVariable = GPUVerifier.MakeOffsetVariable(v.Name, Access);
+ Variable AccessSourceVariable = GPUVerifier.MakeSourceVariable(v.Name, Access);
+
+ Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool));
+
+ Debug.Assert(v.TypedIdent.Type is MapType);
+ MapType mt = v.TypedIdent.Type as MapType;
+ Debug.Assert(mt.Arguments.Length == 1);
+ Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0]));
+ Variable SourceParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_source", mt.Arguments[0]));
+ Debug.Assert(!(mt.Result is MapType));
+
+ VariableSeq locals = new VariableSeq();
+ Variable TrackVariable = new LocalVariable(v.tok, new TypedIdent(v.tok, "track", Microsoft.Boogie.Type.Bool));
+ locals.Add(TrackVariable);
+
+ List<BigBlock> bigblocks = new List<BigBlock>();
+
+ CmdSeq simpleCmds = new CmdSeq();
+
+ simpleCmds.Add(new HavocCmd(v.tok, new IdentifierExprSeq(new IdentifierExpr[] { new IdentifierExpr(v.tok, TrackVariable) })));
+
+ simpleCmds.Add(MakeConditionalAssignment(VariableForThread(1, AccessHasOccurredVariable),
+ Expr.And(new IdentifierExpr(v.tok, VariableForThread(1, PredicateParameter)), new IdentifierExpr(v.tok, TrackVariable)), Expr.True));
+ simpleCmds.Add(MakeConditionalAssignment(VariableForThread(1, AccessOffsetXVariable),
+ Expr.And(new IdentifierExpr(v.tok, VariableForThread(1, PredicateParameter)), new IdentifierExpr(v.tok, TrackVariable)),
+ new IdentifierExpr(v.tok, VariableForThread(1, OffsetParameter))));
+ simpleCmds.Add(MakeConditionalAssignment(VariableForThread(1, AccessSourceVariable),
+ Expr.And(new IdentifierExpr(v.tok, VariableForThread(1, PredicateParameter)), new IdentifierExpr(v.tok, TrackVariable)),
+ new IdentifierExpr(v.tok, VariableForThread(1, SourceParameter))));
+
+ bigblocks.Add(new BigBlock(v.tok, "_LOG_" + Access + "", simpleCmds, null, null));
+
+ LogAccessProcedure.Modifies.Add(new IdentifierExpr(Token.NoToken, VariableForThread(1, AccessHasOccurredVariable)));
+ LogAccessProcedure.Modifies.Add(new IdentifierExpr(Token.NoToken, VariableForThread(1, AccessOffsetXVariable)));
+
+ Implementation LogAccessImplementation = new Implementation(v.tok, "_LOG_" + Access + "_" + v.Name, new TypeVariableSeq(), LogAccessProcedure.InParams, new VariableSeq(), locals, new StmtList(bigblocks, v.tok));
+ LogAccessImplementation.AddAttribute("inline", new object[] { new LiteralExpr(v.tok, BigNum.FromInt(1)) });
+
+ LogAccessImplementation.Proc = LogAccessProcedure;
+
+ verifier.Program.TopLevelDeclarations.Add(LogAccessProcedure);
+ verifier.Program.TopLevelDeclarations.Add(LogAccessImplementation);
+ }
+
+
+ protected void AddCheckAccessProcedure(Variable v, string Access) {
+ Procedure CheckAccessProcedure = MakeCheckAccessProcedureHeader(v, Access);
+
+ Variable AccessHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, Access);
+ Variable AccessOffsetXVariable = GPUVerifier.MakeOffsetVariable(v.Name, Access);
+
+ Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool));
+
+ Debug.Assert(v.TypedIdent.Type is MapType);
+ MapType mt = v.TypedIdent.Type as MapType;
+ Debug.Assert(mt.Arguments.Length == 1);
+ Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0]));
+ Debug.Assert(!(mt.Result is MapType));
+
+ if (Access.Equals("READ")) {
+ // Check read by thread 2 does not conflict with write by thread 1
+ Variable WriteHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE");
+ Variable WriteOffsetVariable = GPUVerifier.MakeOffsetVariable(v.Name, "WRITE");
+ Expr WriteReadGuard = new IdentifierExpr(Token.NoToken, VariableForThread(2, PredicateParameter));
+ WriteReadGuard = Expr.And(WriteReadGuard, new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteHasOccurredVariable)));
+ WriteReadGuard = Expr.And(WriteReadGuard, Expr.Eq(new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteOffsetVariable)),
+ new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter))));
+
+ if (!verifier.ArrayModelledAdversarially(v)) {
+ WriteReadGuard = Expr.And(WriteReadGuard, Expr.Neq(
+ new VariableDualiser(1, null, null).VisitExpr(
+ MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, WriteOffsetVariable), "WRITE")),
+ new VariableDualiser(2, null, null).VisitExpr(
+ MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, OffsetParameter), "READ"))
+ ));
+ }
+
+ if (verifier.KernelArrayInfo.getGroupSharedArrays().Contains(v)) {
+ WriteReadGuard = Expr.And(WriteReadGuard, GPUVerifier.ThreadsInSameGroup());
+ }
+
+ WriteReadGuard = Expr.Not(WriteReadGuard);
+
+ Requires NoWriteReadRaceRequires = new Requires(false, WriteReadGuard);
+ QKeyValue kv = new QKeyValue(Token.NoToken, "write_read", new List<object>(), null);
+ NoWriteReadRaceRequires.Attributes = new QKeyValue(Token.NoToken, "race", new List<object>(), kv);
+ CheckAccessProcedure.Requires.Add(NoWriteReadRaceRequires);
+ }
+ else {
+ Debug.Assert(Access.Equals("WRITE"));
+
+ // Check write by thread 2 does not conflict with write by thread 1
+ Variable WriteHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE");
+ Variable WriteOffsetVariable = GPUVerifier.MakeOffsetVariable(v.Name, "WRITE");
+
+ Expr WriteWriteGuard = new IdentifierExpr(Token.NoToken, VariableForThread(2, PredicateParameter));
+ WriteWriteGuard = Expr.And(WriteWriteGuard, new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteHasOccurredVariable)));
+ WriteWriteGuard = Expr.And(WriteWriteGuard, Expr.Eq(new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteOffsetVariable)),
+ new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter))));
+ if (!verifier.ArrayModelledAdversarially(v)) {
+ WriteWriteGuard = Expr.And(WriteWriteGuard, Expr.Neq(
+ new VariableDualiser(1, null, null).VisitExpr(
+ MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, WriteOffsetVariable), "WRITE")),
+ new VariableDualiser(2, null, null).VisitExpr(
+ MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, OffsetParameter), "WRITE"))
+ ));
+ }
+
+ if (verifier.KernelArrayInfo.getGroupSharedArrays().Contains(v)) {
+ WriteWriteGuard = Expr.And(WriteWriteGuard, GPUVerifier.ThreadsInSameGroup());
+ }
+
+ WriteWriteGuard = Expr.Not(WriteWriteGuard);
+ Requires NoWriteWriteRaceRequires = new Requires(false, WriteWriteGuard);
+ QKeyValue kv = new QKeyValue(Token.NoToken, "write_write", new List<object>(), null);
+ NoWriteWriteRaceRequires.Attributes = new QKeyValue(Token.NoToken, "race", new List<object>(), kv);
+ CheckAccessProcedure.Requires.Add(NoWriteWriteRaceRequires);
+
+ // Check write by thread 2 does not conflict with read by thread 1
+ Variable ReadHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ");
+ Variable ReadOffsetVariable = GPUVerifier.MakeOffsetVariable(v.Name, "READ");
+
+ Expr ReadWriteGuard = new IdentifierExpr(Token.NoToken, VariableForThread(2, PredicateParameter));
+ ReadWriteGuard = Expr.And(ReadWriteGuard, new IdentifierExpr(Token.NoToken, VariableForThread(1, ReadHasOccurredVariable)));
+ ReadWriteGuard = Expr.And(ReadWriteGuard, Expr.Eq(new IdentifierExpr(Token.NoToken, VariableForThread(1, ReadOffsetVariable)),
+ new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter))));
+ if (!verifier.ArrayModelledAdversarially(v)) {
+ ReadWriteGuard = Expr.And(ReadWriteGuard, Expr.Neq(
+ new VariableDualiser(1, null, null).VisitExpr(
+ MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, ReadOffsetVariable), "WRITE")),
+ new VariableDualiser(2, null, null).VisitExpr(
+ MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, OffsetParameter), "READ"))
+ ));
+ }
+
+ if (verifier.KernelArrayInfo.getGroupSharedArrays().Contains(v)) {
+ ReadWriteGuard = Expr.And(ReadWriteGuard, GPUVerifier.ThreadsInSameGroup());
+ }
+
+ ReadWriteGuard = Expr.Not(ReadWriteGuard);
+ Requires NoReadWriteRaceRequires = new Requires(false, ReadWriteGuard);
+ kv = new QKeyValue(Token.NoToken, "read_write", new List<object>(), null);
+ NoReadWriteRaceRequires.Attributes = new QKeyValue(Token.NoToken, "race", new List<object>(), kv);
+ CheckAccessProcedure.Requires.Add(NoReadWriteRaceRequires);
+
+ }
+ verifier.Program.TopLevelDeclarations.Add(CheckAccessProcedure);
+ }
+
+
+
+ private Variable VariableForThread(int thread, Variable v) {
+ return new VariableDualiser(thread, null, null).VisitVariable(v.Clone() as Variable);
+ }
+
+ protected void AddLogRaceDeclarations(Variable v, String ReadOrWrite) {
+ verifier.FindOrCreateAccessHasOccurredVariable(v.Name, ReadOrWrite);
+
+ Debug.Assert(v.TypedIdent.Type is MapType);
+ MapType mt = v.TypedIdent.Type as MapType;
+ Debug.Assert(mt.Arguments.Length == 1);
+
+ verifier.FindOrCreateOffsetVariable(v.Name, ReadOrWrite);
+ verifier.FindOrCreateSourceVariable(v.Name, ReadOrWrite);
+
+ }
+
+
+ private static AssignCmd MakeConditionalAssignment(Variable lhs, Expr condition, Expr rhs) {
+ List<AssignLhs> lhss = new List<AssignLhs>();
+ List<Expr> rhss = new List<Expr>();
+ lhss.Add(new SimpleAssignLhs(lhs.tok, new IdentifierExpr(lhs.tok, lhs)));
+ rhss.Add(new NAryExpr(rhs.tok, new IfThenElse(rhs.tok), new ExprSeq(new Expr[] { condition, rhs, new IdentifierExpr(lhs.tok, lhs) })));
+ return new AssignCmd(lhs.tok, lhss, rhss);
+ }
+
+ private Expr MakeAccessedIndex(Variable v, Expr offsetExpr, string AccessType) {
+ Expr result = new IdentifierExpr(v.tok, v.Clone() as Variable);
+ Debug.Assert(v.TypedIdent.Type is MapType);
+ MapType mt = v.TypedIdent.Type as MapType;
+ Debug.Assert(mt.Arguments.Length == 1);
+
+ result = Expr.Select(result,
+ new Expr[] { offsetExpr });
+ Debug.Assert(!(mt.Result is MapType));
+ return result;
+ }
+
+ protected void AddRequiresNoPendingAccess(Variable v) {
+ IdentifierExpr ReadAccessOccurred1 = new IdentifierExpr(v.tok, new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ")));
+ IdentifierExpr WriteAccessOccurred1 = new IdentifierExpr(v.tok, new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE")));
+
+ verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.And(Expr.Not(ReadAccessOccurred1), Expr.Not(WriteAccessOccurred1))));
+ }
+
+ private void AddRequiresSourceAccessZero(Variable v)
+ {
+ verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(v.Name, "READ")),
+ GPUVerifier.ZeroBV())));
+ verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(v.Name, "WRITE")),
+ GPUVerifier.ZeroBV())));
+ }
+
+ public void AddSourceLocationLoopInvariants(Implementation impl, IRegion region)
+ {
+ foreach (string key in WriteAccessSourceLocations.Keys.Union(ReadAccessSourceLocations.Keys))
+ {
+ region.AddInvariant(BuildNoAccessInvariant(key, "WRITE"));
+ region.AddInvariant(BuildNoAccessInvariant(key, "READ"));
+
+ if (WriteAccessSourceLocations.ContainsKey(key))
+ {
+ region.AddInvariant(BuildPossibleSourceLocationsInvariant(key, "WRITE"));
+ }
+ else
+ {
+ region.AddInvariant(BuildAccessOccurredFalseInvariant(key, "WRITE"));
+ }
+
+ if (ReadAccessSourceLocations.ContainsKey(key))
+ {
+ region.AddInvariant(BuildPossibleSourceLocationsInvariant(key, "READ"));
+ }
+ else
+ {
+ region.AddInvariant(BuildAccessOccurredFalseInvariant(key, "READ"));
+ }
+ }
+ }
+
+ public void AddStandardSourceVariablePreconditions()
+ {
+ foreach (Declaration D in verifier.Program.TopLevelDeclarations.ToList())
+ {
+ if (!(D is Procedure))
+ {
+ continue;
+ }
+ Procedure Proc = D as Procedure;
+ foreach (string key in WriteAccessSourceLocations.Keys.Union(ReadAccessSourceLocations.Keys))
+ {
+ Proc.Requires.Add(new Requires(false, BuildNoAccessExpr(key, "WRITE")));
+ Proc.Requires.Add(new Requires(false, BuildNoAccessExpr(key, "READ")));
+
+ if (WriteAccessSourceLocations.ContainsKey(key))
+ {
+ Proc.Requires.Add(new Requires(false, BuildPossibleSourceLocationsExpr(key, "WRITE")));
+ }
+ else
+ {
+ Proc.Requires.Add(new Requires(false, BuildAccessOccurredFalseExpr(key, "WRITE")));
+ }
+
+ if (ReadAccessSourceLocations.ContainsKey(key))
+ {
+ Proc.Requires.Add(new Requires(false, BuildPossibleSourceLocationsExpr(key, "READ")));
+ }
+ else
+ {
+ Proc.Requires.Add(new Requires(false, BuildAccessOccurredFalseExpr(key, "READ")));
+ }
+ }
+ }
+ }
+
+ public void AddStandardSourceVariablePostconditions()
+ {
+ foreach (Declaration D in verifier.Program.TopLevelDeclarations.ToList())
+ {
+ if (!(D is Procedure))
+ {
+ continue;
+ }
+ Procedure Proc = D as Procedure;
+ foreach (string key in WriteAccessSourceLocations.Keys.Union(ReadAccessSourceLocations.Keys))
+ {
+ Proc.Ensures.Add(new Ensures(false, BuildNoAccessExpr(key, "WRITE")));
+ Proc.Ensures.Add(new Ensures(false, BuildNoAccessExpr(key, "READ")));
+
+ if (WriteAccessSourceLocations.ContainsKey(key))
+ {
+ Proc.Ensures.Add(new Ensures(false, BuildPossibleSourceLocationsExpr(key, "WRITE")));
+ }
+ else
+ {
+ Proc.Ensures.Add(new Ensures(false, BuildAccessOccurredFalseExpr(key, "WRITE")));
+ }
+
+ if (ReadAccessSourceLocations.ContainsKey(key))
+ {
+ Proc.Ensures.Add(new Ensures(false, BuildPossibleSourceLocationsExpr(key, "READ")));
+ }
+ else
+ {
+ Proc.Ensures.Add(new Ensures(false, BuildAccessOccurredFalseExpr(key, "READ")));
+ }
+ }
+ }
+ }
+
+ private Expr BuildAccessOccurredFalseExpr(string name, string AccessType)
+ {
+ return Expr.Imp(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateAccessHasOccurredVariable(name, AccessType)),
+ Expr.False);
+ }
+
+ private AssertCmd BuildAccessOccurredFalseInvariant(string name, string AccessType)
+ {
+ return new AssertCmd(Token.NoToken, BuildAccessOccurredFalseExpr(name, AccessType));
+ }
+
+ private Expr BuildNoAccessExpr(string name, string AccessType)
+ {
+ return Expr.Imp(Expr.Not(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateAccessHasOccurredVariable(name, AccessType))),
+ Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(name, AccessType)),
+ new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 32)));
+ }
+
+ private AssertCmd BuildNoAccessInvariant(string name, string AccessType)
+ {
+ return new AssertCmd(Token.NoToken, BuildNoAccessExpr(name, AccessType));
+ }
+
+ private Expr BuildPossibleSourceLocationsExpr(string name, string AccessType)
+ {
+ return Expr.Imp(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateAccessHasOccurredVariable(name, AccessType)),
+ BuildDisjunctionFromAccessSourceLocations(name, AccessType));
+ }
+
+ private AssertCmd BuildPossibleSourceLocationsInvariant(string name, string AccessType)
+ {
+ return new AssertCmd(Token.NoToken, BuildPossibleSourceLocationsExpr(name, AccessType));
+ }
+
+ private Expr BuildDisjunctionFromAccessSourceLocations(string key, string AccessType)
+ {
+ List<Expr> sourceLocExprs = new List<Expr>();
+ Dictionary<string, List<int>> AccessSourceLocations = (AccessType.Equals("WRITE")) ? WriteAccessSourceLocations : ReadAccessSourceLocations;
+ foreach (int loc in AccessSourceLocations[key])
+ {
+ sourceLocExprs.Add(Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(key, AccessType)),
+ new LiteralExpr(Token.NoToken, BigNum.FromInt(loc), 32)));
+ }
+ return sourceLocExprs.Aggregate(Expr.Or);
+ }
+
+ protected Expr NoReadOrWriteExpr(Variable v, string ReadOrWrite, string OneOrTwo) {
+ Variable ReadOrWriteHasOccurred = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite);
+ ReadOrWriteHasOccurred.Name = ReadOrWriteHasOccurred.Name + "$" + OneOrTwo;
+ ReadOrWriteHasOccurred.TypedIdent.Name = ReadOrWriteHasOccurred.TypedIdent.Name + "$" + OneOrTwo;
+ Expr expr = Expr.Not(new IdentifierExpr(v.tok, ReadOrWriteHasOccurred));
+ return expr;
+ }
+
+
+ protected void AddOffsetsSatisfyPredicatesCandidateInvariant(IRegion region, Variable v, string ReadOrWrite, List<Expr> preds) {
+ if (preds.Count != 0) {
+ Expr expr = AccessedOffsetsSatisfyPredicatesExpr(v, preds, ReadOrWrite, 1);
+ verifier.AddCandidateInvariant(region, expr, "accessed offsets satisfy predicates");
+ }
+ }
+
+ private Expr AccessedOffsetsSatisfyPredicatesExpr(Variable v, IEnumerable<Expr> offsets, string ReadOrWrite, int Thread) {
+ return Expr.Imp(
+ new IdentifierExpr(Token.NoToken, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite))),
+ offsets.Aggregate(Expr.Or));
+ }
+
+ private Expr AccessedOffsetIsThreadLocalIdExpr(Variable v, string ReadOrWrite, int Thread) {
+ return Expr.Imp(
+ new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite))),
+ Expr.Eq(new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeOffsetVariable(v.Name, ReadOrWrite))),
+ new IdentifierExpr(v.tok, GPUVerifier.MakeThreadId("X", Thread))));
+ }
+
+ private Expr GlobalIdExpr(string dimension, int Thread) {
+ return new VariableDualiser(Thread, null, null).VisitExpr(verifier.GlobalIdExpr(dimension).Clone() as Expr);
+ }
+
+ protected void AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(IRegion region, Variable v, Expr constant, string ReadOrWrite) {
+ Expr expr = MakeCTimesLocalIdRangeExpression(v, constant, ReadOrWrite, 1);
+ verifier.AddCandidateInvariant(region,
+ expr, "accessed offset in range [ C*local_id, (C+1)*local_id )");
+ }
+
+ private Expr MakeCTimesLocalIdRangeExpression(Variable v, Expr constant, string ReadOrWrite, int Thread) {
+ Expr CTimesLocalId = verifier.MakeBVMul(constant.Clone() as Expr,
+ new IdentifierExpr(Token.NoToken, GPUVerifier.MakeThreadId("X", Thread)));
+
+ Expr CTimesLocalIdPlusC = verifier.MakeBVAdd(verifier.MakeBVMul(constant.Clone() as Expr,
+ new IdentifierExpr(Token.NoToken, GPUVerifier.MakeThreadId("X", Thread))), constant.Clone() as Expr);
+
+ Expr CTimesLocalIdLeqAccessedOffset = GPUVerifier.MakeBitVectorBinaryBoolean("BV32_LEQ", CTimesLocalId, OffsetXExpr(v, ReadOrWrite, Thread));
+
+ Expr AccessedOffsetLtCTimesLocalIdPlusC = verifier.MakeBVSlt(OffsetXExpr(v, ReadOrWrite, Thread), CTimesLocalIdPlusC);
+
+ return Expr.Imp(
+ AccessHasOccurred(v, ReadOrWrite, Thread),
+ Expr.And(CTimesLocalIdLeqAccessedOffset, AccessedOffsetLtCTimesLocalIdPlusC));
+ }
+
+ private static IdentifierExpr AccessHasOccurred(Variable v, string ReadOrWrite, int Thread) {
+ return new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite)));
+ }
+
+ private static IdentifierExpr OffsetXExpr(Variable v, string ReadOrWrite, int Thread) {
+ return new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeOffsetVariable(v.Name, ReadOrWrite)));
+ }
+
+ protected void AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(IRegion region, Variable v, Expr constant, string ReadOrWrite) {
+ Expr expr = MakeCTimesGloalIdRangeExpr(v, constant, ReadOrWrite, 1);
+ verifier.AddCandidateInvariant(region,
+ expr, "accessed offset in range [ C*global_id, (C+1)*global_id )");
+ }
+
+ private Expr MakeCTimesGloalIdRangeExpr(Variable v, Expr constant, string ReadOrWrite, int Thread) {
+ Expr CTimesGlobalId = verifier.MakeBVMul(constant.Clone() as Expr,
+ GlobalIdExpr("X", Thread));
+
+ Expr CTimesGlobalIdPlusC = verifier.MakeBVAdd(verifier.MakeBVMul(constant.Clone() as Expr,
+ GlobalIdExpr("X", Thread)), constant.Clone() as Expr);
+
+ Expr CTimesGlobalIdLeqAccessedOffset = GPUVerifier.MakeBitVectorBinaryBoolean("BV32_LEQ", CTimesGlobalId, OffsetXExpr(v, ReadOrWrite, Thread));
+
+ Expr AccessedOffsetLtCTimesGlobalIdPlusC = verifier.MakeBVSlt(OffsetXExpr(v, ReadOrWrite, Thread), CTimesGlobalIdPlusC);
+
+ Expr implication = Expr.Imp(
+ AccessHasOccurred(v, ReadOrWrite, Thread),
+ Expr.And(CTimesGlobalIdLeqAccessedOffset, AccessedOffsetLtCTimesGlobalIdPlusC));
+ return implication;
+ }
+
+ private void writeSourceLocToFile(QKeyValue kv, string path) {
+ TextWriter tw = new StreamWriter(path, true);
+ tw.Write("\n" + QKeyValue.FindIntAttribute(SourceLocationAttributes, "line", -1)
+ + "#" + QKeyValue.FindIntAttribute(SourceLocationAttributes, "col", -1)
+ + "#" + QKeyValue.FindStringAttribute(SourceLocationAttributes, "fname")
+ + "#" + QKeyValue.FindStringAttribute(SourceLocationAttributes, "dir"));
+ tw.Close();
+ }
+
+ protected void AddAccessedOffsetIsThreadLocalIdCandidateRequires(Procedure Proc, Variable v, string ReadOrWrite, int Thread) {
+ verifier.AddCandidateRequires(Proc, AccessedOffsetIsThreadLocalIdExpr(v, ReadOrWrite, Thread));
+ }
+
+ protected void AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Procedure Proc, Variable v, string ReadOrWrite, int Thread) {
+ verifier.AddCandidateEnsures(Proc, AccessedOffsetIsThreadLocalIdExpr(v, ReadOrWrite, Thread));
+ }
+
+
+
+ }
+
+
+
+ class FindReferencesToNamedVariableVisitor : StandardVisitor {
+ internal bool found = false;
+ private string name;
+
+ internal FindReferencesToNamedVariableVisitor(string name) {
+ this.name = name;
+ }
+
+ public override Variable VisitVariable(Variable node) {
+ if (GPUVerifier.StripThreadIdentifier(node.Name).Equals(name)) {
+ found = true;
+ }
+ return base.VisitVariable(node);
+ }
+ }
+
+
+
+}
diff --git a/Source/GPUVerify/UnaryBarrierInvariantDescriptor.cs b/Source/GPUVerify/UnaryBarrierInvariantDescriptor.cs
new file mode 100644
index 00000000..48e3a2ec
--- /dev/null
+++ b/Source/GPUVerify/UnaryBarrierInvariantDescriptor.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+
+namespace GPUVerify {
+ class UnaryBarrierInvariantDescriptor : BarrierInvariantDescriptor {
+ private List<Expr> InstantiationExprs;
+
+ public UnaryBarrierInvariantDescriptor(Expr Predicate, Expr BarrierInvariant,
+ QKeyValue SourceLocationInfo, KernelDualiser Dualiser, string ProcName) :
+ base(Predicate, BarrierInvariant, SourceLocationInfo, Dualiser, ProcName) {
+ InstantiationExprs = new List<Expr>();
+ }
+
+ public void AddInstantiationExpr(Expr InstantiationExpr) {
+ InstantiationExprs.Add(InstantiationExpr);
+ }
+
+ internal override AssertCmd GetAssertCmd() {
+ var vd = new VariableDualiser(1, Dualiser.verifier.uniformityAnalyser, ProcName);
+ return new AssertCmd(
+ Token.NoToken,
+ vd.VisitExpr(Expr.Imp(Predicate, BarrierInvariant)),
+ Dualiser.MakeThreadSpecificAttributes(SourceLocationInfo, 1));
+ }
+
+ internal override List<AssumeCmd> GetInstantiationCmds() {
+ var result = new List<AssumeCmd>();
+ foreach (var Instantiation in InstantiationExprs) {
+ foreach (var Thread in new int[] { 1, 2 }) {
+ var vd = new VariableDualiser(Thread, Dualiser.verifier.uniformityAnalyser, ProcName);
+ var ThreadInstantiationExpr = vd.VisitExpr(Instantiation);
+ var ti = new ThreadInstantiator(ThreadInstantiationExpr, Thread,
+ Dualiser.verifier.uniformityAnalyser, ProcName);
+
+ result.Add(new AssumeCmd(
+ Token.NoToken,
+ Expr.Imp(vd.VisitExpr(Predicate),
+ Expr.Imp(Expr.And(
+ NonNegative(ThreadInstantiationExpr),
+ NotTooLarge(ThreadInstantiationExpr)),
+ ti.VisitExpr(BarrierInvariant)))));
+ }
+ }
+ return result;
+ }
+
+ }
+}
diff --git a/Source/GPUVerify/UniformExpressionAnalysisVisitor.cs b/Source/GPUVerify/UniformExpressionAnalysisVisitor.cs
deleted file mode 100644
index 76f6b5de..00000000
--- a/Source/GPUVerify/UniformExpressionAnalysisVisitor.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-
-namespace GPUVerify
-{
- class UniformExpressionAnalysisVisitor : StandardVisitor
- {
-
- private bool isUniform = true;
- private Dictionary<string, bool> uniformityInfo;
-
- public UniformExpressionAnalysisVisitor(Dictionary<string, bool> uniformityInfo)
- {
- this.uniformityInfo = uniformityInfo;
- }
-
- public override Variable VisitVariable(Variable v)
- {
- if (!uniformityInfo.ContainsKey(v.Name))
- {
- isUniform = isUniform && (v is Constant);
- }
- else if (!uniformityInfo[v.Name])
- {
- isUniform = false;
- }
-
- return v;
- }
-
- internal bool IsUniform()
- {
- return isUniform;
- }
- }
-}
diff --git a/Source/GPUVerify/UniformityAnalyser.cs b/Source/GPUVerify/UniformityAnalyser.cs
deleted file mode 100644
index 35f297ed..00000000
--- a/Source/GPUVerify/UniformityAnalyser.cs
+++ /dev/null
@@ -1,425 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-using System.Diagnostics;
-
-namespace GPUVerify
-{
-
- class UniformityAnalyser
- {
- private GPUVerifier verifier;
-
- private bool ProcedureChanged;
-
- private Dictionary<string, KeyValuePair<bool, Dictionary<string, bool>>> uniformityInfo;
-
- private Dictionary<string, HashSet<int>> nonUniformLoops;
-
- private Dictionary<string, HashSet<int>> loopsWithNonuniformReturn;
-
- private Dictionary<string, List<string>> inParameters;
-
- private Dictionary<string, List<string>> outParameters;
-
- private List<WhileCmd> loopStack;
-
- private bool hitNonuniformReturn;
-
- public UniformityAnalyser(GPUVerifier verifier)
- {
- this.verifier = verifier;
- uniformityInfo = new Dictionary<string, KeyValuePair<bool, Dictionary<string, bool>>>();
- nonUniformLoops = new Dictionary<string, HashSet<int>>();
- loopsWithNonuniformReturn = new Dictionary<string, HashSet<int>>();
- inParameters = new Dictionary<string, List<string>>();
- outParameters = new Dictionary<string, List<string>>();
- loopStack = new List<WhileCmd>();
- }
-
- internal void Analyse()
- {
- if (CommandLineOptions.Unstructured)
- return;
-
- foreach (Declaration D in verifier.Program.TopLevelDeclarations)
- {
- if(D is Implementation)
- {
- bool uniformProcedure =
- (D == verifier.KernelImplementation
- || CommandLineOptions.DoUniformityAnalysis);
-
- Implementation Impl = D as Implementation;
- uniformityInfo.Add(Impl.Name, new KeyValuePair<bool, Dictionary<string, bool>>
- (uniformProcedure, new Dictionary<string, bool> ()));
-
- nonUniformLoops.Add(Impl.Name, new HashSet<int>());
- loopsWithNonuniformReturn.Add(Impl.Name, new HashSet<int>());
-
- SetNonUniform(Impl.Name, GPUVerifier._X.Name);
- SetNonUniform(Impl.Name, GPUVerifier._Y.Name);
- SetNonUniform(Impl.Name, GPUVerifier._Z.Name);
-
- SetNonUniform(Impl.Name, GPUVerifier._GROUP_X.Name);
- SetNonUniform(Impl.Name, GPUVerifier._GROUP_Y.Name);
- SetNonUniform(Impl.Name, GPUVerifier._GROUP_Z.Name);
-
- foreach (Variable v in Impl.LocVars)
- {
- if (CommandLineOptions.DoUniformityAnalysis)
- {
- SetUniform(Impl.Name, v.Name);
- }
- else
- {
- SetNonUniform(Impl.Name, v.Name);
- }
- }
-
- inParameters[Impl.Name] = new List<string>();
-
- foreach (Variable v in Impl.InParams)
- {
- inParameters[Impl.Name].Add(v.Name);
- if (CommandLineOptions.DoUniformityAnalysis)
- {
- SetUniform(Impl.Name, v.Name);
- }
- else
- {
- SetNonUniform(Impl.Name, v.Name);
- }
- }
-
- outParameters[Impl.Name] = new List<string>();
- foreach (Variable v in Impl.OutParams)
- {
- outParameters[Impl.Name].Add(v.Name);
- if (CommandLineOptions.DoUniformityAnalysis)
- {
- SetUniform(Impl.Name, v.Name);
- }
- else
- {
- SetNonUniform(Impl.Name, v.Name);
- }
- }
-
- ProcedureChanged = true;
- }
- }
-
- if (CommandLineOptions.DoUniformityAnalysis)
- {
- while (ProcedureChanged)
- {
- ProcedureChanged = false;
-
- foreach (Declaration D in verifier.Program.TopLevelDeclarations)
- {
- if (D is Implementation)
- {
- hitNonuniformReturn = false;
- Implementation Impl = D as Implementation;
- Analyse(Impl, uniformityInfo[Impl.Name].Key);
- }
- }
- }
- }
-
- foreach (Declaration D in verifier.Program.TopLevelDeclarations)
- {
- if (D is Implementation)
- {
- Implementation Impl = D as Implementation;
- if (!IsUniform (Impl.Name))
- {
- List<string> newIns = new List<String>();
- newIns.Add("_P");
- foreach (string s in inParameters[Impl.Name])
- {
- newIns.Add(s);
- }
- inParameters[Impl.Name] = newIns;
- }
- }
- }
-
- if (CommandLineOptions.ShowUniformityAnalysis)
- {
- dump();
- }
- }
-
- private void Analyse(Implementation Impl, bool ControlFlowIsUniform)
- {
- Analyse(Impl, Impl.StructuredStmts, ControlFlowIsUniform);
- }
-
-
- private void Analyse(Implementation impl, StmtList stmtList, bool ControlFlowIsUniform)
- {
- ControlFlowIsUniform &= !hitNonuniformReturn;
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- Analyse(impl, bb, ControlFlowIsUniform);
- }
- }
-
- private void Analyse(Implementation impl, BigBlock bb, bool ControlFlowIsUniform)
- {
- ControlFlowIsUniform &= !hitNonuniformReturn;
- foreach (Cmd c in bb.simpleCmds)
- {
- if (c is AssignCmd)
- {
- AssignCmd assignCmd = c as AssignCmd;
- Debug.Assert(assignCmd.Lhss.Count == 1);
- Debug.Assert(assignCmd.Rhss.Count == 1);
- if (assignCmd.Lhss[0] is SimpleAssignLhs)
- {
- SimpleAssignLhs lhs = assignCmd.Lhss[0] as SimpleAssignLhs;
- Expr rhs = assignCmd.Rhss[0];
-
- if (IsUniform(impl.Name, lhs.AssignedVariable.Name) &&
- (!ControlFlowIsUniform || !IsUniform(impl.Name, rhs)))
- {
- SetNonUniform(impl.Name, lhs.AssignedVariable.Name);
- }
-
- }
- }
- else if (c is CallCmd)
- {
- CallCmd callCmd = c as CallCmd;
-
- if (callCmd.callee != verifier.BarrierProcedure.Name)
- {
-
- if (!ControlFlowIsUniform)
- {
- if (IsUniform(callCmd.callee))
- {
- SetNonUniform(callCmd.callee);
- }
- }
- Implementation CalleeImplementation = verifier.GetImplementation(callCmd.callee);
- for (int i = 0; i < CalleeImplementation.InParams.Length; i++)
- {
- if (IsUniform(callCmd.callee, CalleeImplementation.InParams[i].Name)
- && !IsUniform(impl.Name, callCmd.Ins[i]))
- {
- SetNonUniform(callCmd.callee, CalleeImplementation.InParams[i].Name);
- }
- }
-
- for (int i = 0; i < CalleeImplementation.OutParams.Length; i++)
- {
- if (IsUniform(impl.Name, callCmd.Outs[i].Name)
- && !IsUniform(callCmd.callee, CalleeImplementation.OutParams[i].Name))
- {
- SetNonUniform(impl.Name, callCmd.Outs[i].Name);
- }
- }
-
- }
- }
- }
-
- if (bb.ec is WhileCmd)
- {
- WhileCmd wc = bb.ec as WhileCmd;
- loopStack.Add(wc);
- Analyse(impl, wc.Body, ControlFlowIsUniform && IsUniform(impl.Name, wc.Guard) &&
- !nonUniformLoops[impl.Name].Contains(GetLoopId(wc)));
- loopStack.RemoveAt(loopStack.Count - 1);
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd ifCmd = bb.ec as IfCmd;
- Analyse(impl, ifCmd.thn, ControlFlowIsUniform && IsUniform(impl.Name, ifCmd.Guard));
- if (ifCmd.elseBlock != null)
- {
- Analyse(impl, ifCmd.elseBlock, ControlFlowIsUniform && IsUniform(impl.Name, ifCmd.Guard));
- }
- Debug.Assert(ifCmd.elseIf == null);
- }
- else if (bb.ec is BreakCmd)
- {
- if (!ControlFlowIsUniform && !nonUniformLoops[impl.Name].Contains(GetLoopId(loopStack[loopStack.Count - 1])))
- {
- SetNonUniform(impl.Name, loopStack[loopStack.Count - 1]);
- }
- }
-
- if (bb.tc is ReturnCmd && !ControlFlowIsUniform)
- {
- hitNonuniformReturn = true;
- if (loopStack.Count > 0 && !nonUniformLoops[impl.Name].Contains(GetLoopId(loopStack[0])))
- {
- SetNonUniform(impl.Name, loopStack[0]);
- loopsWithNonuniformReturn[impl.Name].Add(GetLoopId(loopStack[0]));
- }
- }
-
-
- }
-
- private int GetLoopId(WhileCmd wc)
- {
- AssertCmd inv = wc.Invariants[0] as AssertCmd;
- Debug.Assert(inv.Attributes.Key.Contains("loophead_"));
- return Convert.ToInt32(inv.Attributes.Key.Substring("loophead_".Length));
- }
-
- private void SetNonUniform(string procedureName)
- {
- uniformityInfo[procedureName] = new KeyValuePair<bool,Dictionary<string,bool>>
- (false, uniformityInfo[procedureName].Value);
- RecordProcedureChanged();
- }
-
- private void SetNonUniform(string procedureName, WhileCmd wc)
- {
- nonUniformLoops[procedureName].Add(GetLoopId(wc));
- RecordProcedureChanged();
- }
-
- internal bool IsUniform(string procedureName)
- {
- if (CommandLineOptions.Unstructured)
- return false;
-
- if (!uniformityInfo.ContainsKey(procedureName))
- {
- return false;
- }
- return uniformityInfo[procedureName].Key;
- }
-
- internal bool IsUniform(string procedureName, Expr expr)
- {
- if (CommandLineOptions.Unstructured)
- return false;
-
- UniformExpressionAnalysisVisitor visitor = new UniformExpressionAnalysisVisitor(uniformityInfo[procedureName].Value);
- visitor.VisitExpr(expr);
- return visitor.IsUniform();
- }
-
- internal bool IsUniform(string procedureName, string v)
- {
- if (CommandLineOptions.Unstructured)
- return false;
-
- if (!uniformityInfo.ContainsKey(procedureName))
- {
- return false;
- }
-
- if (!uniformityInfo[procedureName].Value.ContainsKey(v))
- {
- return false;
- }
- return uniformityInfo[procedureName].Value[v];
- }
-
- private void SetUniform(string procedureName, string v)
- {
- uniformityInfo[procedureName].Value[v] = true;
- RecordProcedureChanged();
- }
-
- private void RecordProcedureChanged()
- {
- ProcedureChanged = true;
- }
-
- private void SetNonUniform(string procedureName, string v)
- {
- uniformityInfo[procedureName].Value[v] = false;
- RecordProcedureChanged();
- }
-
- private void dump()
- {
- foreach (string p in uniformityInfo.Keys)
- {
- Console.WriteLine("Procedure " + p + ": "
- + (uniformityInfo[p].Key ? "uniform" : "nonuniform"));
- foreach (string v in uniformityInfo[p].Value.Keys)
- {
- Console.WriteLine(" " + v + ": " +
- (uniformityInfo[p].Value[v] ? "uniform" : "nonuniform"));
- }
- Console.Write("Ins [");
- for (int i = 0; i < inParameters[p].Count; i++)
- {
- Console.Write((i == 0 ? "" : ", ") + inParameters[p][i]);
- }
- Console.WriteLine("]");
- Console.Write("Outs [");
- for (int i = 0; i < outParameters[p].Count; i++)
- {
- Console.Write((i == 0 ? "" : ", ") + outParameters[p][i]);
- }
- Console.WriteLine("]");
- Console.Write("Non-uniform loops:");
- foreach (int l in nonUniformLoops[p])
- {
- Console.Write(" " + l);
- }
- Console.WriteLine();
- }
- }
-
-
- internal string GetInParameter(string procName, int i)
- {
- if (CommandLineOptions.Unstructured)
- return null;
-
- return inParameters[procName][i];
- }
-
- internal string GetOutParameter(string procName, int i)
- {
- if (CommandLineOptions.Unstructured)
- return null;
-
- return outParameters[procName][i];
- }
-
-
- internal bool knowsOf(string p)
- {
- return uniformityInfo.ContainsKey(p);
- }
-
- internal void AddNonUniform(string proc, string v)
- {
- if (uniformityInfo.ContainsKey(proc))
- {
- Debug.Assert(!uniformityInfo[proc].Value.ContainsKey(v));
- uniformityInfo[proc].Value[v] = false;
- }
- }
-
- internal bool IsUniform(string proc, WhileCmd wc)
- {
- if (CommandLineOptions.Unstructured)
- return false;
-
- return !nonUniformLoops[proc].Contains(GetLoopId(wc));
- }
-
- internal bool HasNonuniformReturn(string proc, WhileCmd whileCmd)
- {
- return loopsWithNonuniformReturn[proc].Contains(GetLoopId(whileCmd));
- }
- }
-
-}
diff --git a/Source/GPUVerify/VariableDualiser.cs b/Source/GPUVerify/VariableDualiser.cs
index d5d9917a..d0b04598 100644
--- a/Source/GPUVerify/VariableDualiser.cs
+++ b/Source/GPUVerify/VariableDualiser.cs
@@ -10,7 +10,7 @@ namespace GPUVerify
{
class VariableDualiser : Duplicator
{
- static HashSet<string> otherFunctionNames =
+ static internal HashSet<string> otherFunctionNames =
new HashSet<string>(new string[] { "__other_bool", "__other_bv32", "__other_arrayId" });
private int id;
@@ -54,13 +54,18 @@ namespace GPUVerify
private TypedIdent DualiseTypedIdent(Variable v)
{
+ if (QKeyValue.FindBoolAttribute(v.Attributes, "global") ||
+ QKeyValue.FindBoolAttribute(v.Attributes, "group_shared")) {
+ return new TypedIdent(v.tok, v.Name, v.TypedIdent.Type);
+ }
- if (uniformityAnalyser == null || !uniformityAnalyser.IsUniform(procName, v.Name))
- {
- return new TypedIdent(v.tok, v.Name + "$" + id, v.TypedIdent.Type);
- }
-
+ if (uniformityAnalyser != null && uniformityAnalyser.IsUniform(procName, v.Name))
+ {
return new TypedIdent(v.tok, v.Name, v.TypedIdent.Type);
+ }
+
+ return new TypedIdent(v.tok, v.Name + "$" + id, v.TypedIdent.Type);
+
}
public override Variable VisitVariable(Variable node)
@@ -79,27 +84,49 @@ namespace GPUVerify
public override Expr VisitNAryExpr(NAryExpr node)
{
- // The point of this override is to avoid dualisation of certain special
- // intrinsics that are cross-thread
-
- if (node.Fun is FunctionCall)
- {
- FunctionCall call = node.Fun as FunctionCall;
+ if (node.Fun is MapSelect) {
+ Debug.Assert((node.Fun as MapSelect).Arity == 1);
+ Debug.Assert(node.Args[0] is IdentifierExpr);
+ var v = (node.Args[0] as IdentifierExpr).Decl;
+ if (QKeyValue.FindBoolAttribute(v.Attributes, "group_shared")) {
+ return new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
+ new ExprSeq(new Expr[] { new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
+ new ExprSeq(new Expr[] { node.Args[0], GPUVerifier.GroupSharedIndexingExpr(id) })),
+ VisitExpr(node.Args[1]) }));
+ }
+ }
- if (otherFunctionNames.Contains(call.Func.Name))
- {
- Debug.Assert(id == 1 || id == 2);
- int otherId = id == 1 ? 2 : 1;
- return new VariableDualiser(otherId, uniformityAnalyser, procName).VisitExpr(
- node.Args[0]);
- }
+ if (node.Fun is FunctionCall)
+ {
+ FunctionCall call = node.Fun as FunctionCall;
+ // Alternate dualisation for "other thread" functions
+ if (otherFunctionNames.Contains(call.Func.Name))
+ {
+ Debug.Assert(id == 1 || id == 2);
+ int otherId = id == 1 ? 2 : 1;
+ return new VariableDualiser(otherId, uniformityAnalyser, procName).VisitExpr(
+ node.Args[0]);
}
- return base.VisitNAryExpr(node);
+ }
+
+ return base.VisitNAryExpr(node);
}
+ public override AssignLhs VisitMapAssignLhs(MapAssignLhs node) {
+
+ var v = node.DeepAssignedVariable;
+ if(QKeyValue.FindBoolAttribute(v.Attributes, "group_shared")) {
+ return new MapAssignLhs(Token.NoToken, new MapAssignLhs(Token.NoToken, node.Map,
+ new List<Expr>(new Expr[] { GPUVerifier.GroupSharedIndexingExpr(id) })),
+ node.Indexes.Select(idx => this.VisitExpr(idx)).ToList());
+
+ }
+ return base.VisitMapAssignLhs(node);
+ }
+
}
}
diff --git a/Source/GPUVerifyBoogieDriver/GPUVerifyBoogieDriver.cs b/Source/GPUVerifyBoogieDriver/GPUVerifyBoogieDriver.cs
index 5b823791..906e0202 100644
--- a/Source/GPUVerifyBoogieDriver/GPUVerifyBoogieDriver.cs
+++ b/Source/GPUVerifyBoogieDriver/GPUVerifyBoogieDriver.cs
@@ -25,7 +25,7 @@ namespace Microsoft.Boogie
using VC;
using AI = Microsoft.AbstractInterpretationFramework;
using BoogiePL = Microsoft.Boogie;
-
+
/*
The following assemblies are referenced because they are needed at runtime, not at compile time:
BaseTypes
@@ -38,39 +38,31 @@ namespace Microsoft.Boogie
// ------------------------------------------------------------------------
// Main
- public static void Main(string[] args)
- {
+ public static void Main(string[] args) {
Contract.Requires(cce.NonNullElements(args));
CommandLineOptions.Install(new CommandLineOptions());
CommandLineOptions.Clo.RunningBoogieFromCommandLine = true;
- if (!CommandLineOptions.Clo.Parse(args))
- {
+ if (!CommandLineOptions.Clo.Parse(args)) {
goto END;
}
- if (CommandLineOptions.Clo.Files.Count == 0)
- {
+ if (CommandLineOptions.Clo.Files.Count == 0) {
ErrorWriteLine("*** Error: No input files were specified.");
goto END;
}
- if (CommandLineOptions.Clo.XmlSink != null)
- {
+ if (CommandLineOptions.Clo.XmlSink != null) {
string errMsg = CommandLineOptions.Clo.XmlSink.Open();
- if (errMsg != null)
- {
+ if (errMsg != null) {
ErrorWriteLine("*** Error: " + errMsg);
goto END;
}
}
- if (!CommandLineOptions.Clo.DontShowLogo)
- {
+ if (!CommandLineOptions.Clo.DontShowLogo) {
Console.WriteLine(CommandLineOptions.Clo.Version);
}
- if (CommandLineOptions.Clo.ShowEnv == CommandLineOptions.ShowEnvironment.Always)
- {
+ if (CommandLineOptions.Clo.ShowEnv == CommandLineOptions.ShowEnvironment.Always) {
Console.WriteLine("---Command arguments");
- foreach (string arg in args)
- {
+ foreach (string arg in args) {
Contract.Assert(arg != null);
Console.WriteLine(arg);
}
@@ -81,34 +73,27 @@ namespace Microsoft.Boogie
Helpers.ExtraTraceInformation("Becoming sentient");
List<string> fileList = new List<string>();
- foreach (string file in CommandLineOptions.Clo.Files)
- {
+ foreach (string file in CommandLineOptions.Clo.Files) {
string extension = Path.GetExtension(file);
- if (extension != null)
- {
+ if (extension != null) {
extension = extension.ToLower();
}
- if (extension == ".txt")
- {
+ if (extension == ".txt") {
StreamReader stream = new StreamReader(file);
string s = stream.ReadToEnd();
fileList.AddRange(s.Split(new char[3] { ' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries));
}
- else
- {
+ else {
fileList.Add(file);
}
}
- foreach (string file in fileList)
- {
+ foreach (string file in fileList) {
Contract.Assert(file != null);
string extension = Path.GetExtension(file);
- if (extension != null)
- {
+ if (extension != null) {
extension = extension.ToLower();
}
- if (extension != ".bpl")
- {
+ if (extension != ".bpl") {
ErrorWriteLine("*** Error: '{0}': Filename extension '{1}' is not supported. Input files must be BoogiePL programs (.bpl).", file,
extension == null ? "" : extension);
goto END;
@@ -117,59 +102,59 @@ namespace Microsoft.Boogie
ProcessFiles(fileList);
END:
- if (CommandLineOptions.Clo.XmlSink != null)
- {
+ if (CommandLineOptions.Clo.XmlSink != null) {
CommandLineOptions.Clo.XmlSink.Close();
}
- if (CommandLineOptions.Clo.Wait)
- {
+ if (CommandLineOptions.Clo.Wait) {
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
}
}
- public static void ErrorWriteLine(string s)
- {
+ public static void ErrorWriteLine(string s) {
Contract.Requires(s != null);
- if (!s.Contains("Error: ") && !s.Contains("Error BP"))
+ ConsoleColor col = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.DarkGray;
+ Console.WriteLine(s);
+ Console.ForegroundColor = col;
+ }
+
+ private static void ErrorWriteLine(string locInfo, string message, ErrorMsgType msgtype)
+ {
+ Contract.Requires(message != null);
+ ConsoleColor col = Console.ForegroundColor;
+ if (!String.IsNullOrEmpty(locInfo))
{
- Console.WriteLine(s);
- return;
+ Console.Write(locInfo + " ");
}
- // split the string up into its first line and the remaining lines
- string remaining = null;
- int i = s.IndexOf('\r');
- if (0 <= i)
+ switch (msgtype)
{
- remaining = s.Substring(i + 1);
- if (remaining.StartsWith("\n"))
- {
- remaining = remaining.Substring(1);
- }
- s = s.Substring(0, i);
+ case ErrorMsgType.Error:
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.Write("error: ");
+ break;
+ case ErrorMsgType.Note:
+ Console.ForegroundColor = ConsoleColor.DarkYellow;
+ Console.Write("note: ");
+ break;
+ case ErrorMsgType.NoError:
+ default:
+ break;
}
+
- ConsoleColor col = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine(s);
Console.ForegroundColor = col;
-
- if (remaining != null)
- {
- Console.WriteLine(remaining);
- }
+ Console.WriteLine(message);
}
- public static void ErrorWriteLine(string format, params object[] args)
- {
+ public static void ErrorWriteLine(string format, params object[] args) {
Contract.Requires(format != null);
string s = string.Format(format, args);
ErrorWriteLine(s);
}
- public static void AdvisoryWriteLine(string format, params object[] args)
- {
+ public static void AdvisoryWriteLine(string format, params object[] args) {
Contract.Requires(format != null);
ConsoleColor col = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;
@@ -177,25 +162,36 @@ namespace Microsoft.Boogie
Console.ForegroundColor = col;
}
- enum FileType
- {
+ enum FileType {
Unknown,
Cil,
Bpl,
Dafny
};
+ enum ErrorMsgType
+ {
+ Error,
+ Note,
+ NoError
+ };
+
+ enum RaceType
+ {
+ WW,
+ RW,
+ WR
+ };
+
static void ProcessFiles(List<string> fileNames)
{
Contract.Requires(cce.NonNullElements(fileNames));
- using (XmlFileScope xf = new XmlFileScope(CommandLineOptions.Clo.XmlSink, fileNames[fileNames.Count - 1]))
- {
+ using (XmlFileScope xf = new XmlFileScope(CommandLineOptions.Clo.XmlSink, fileNames[fileNames.Count - 1])) {
//BoogiePL.Errors.count = 0;
Program program = ParseBoogieProgram(fileNames, false);
if (program == null)
return;
- if (CommandLineOptions.Clo.PrintFile != null)
- {
+ if (CommandLineOptions.Clo.PrintFile != null) {
PrintBplFile(CommandLineOptions.Clo.PrintFile, program, false);
}
@@ -205,19 +201,15 @@ namespace Microsoft.Boogie
//BoogiePL.Errors.count = 0;
// Do bitvector analysis
- if (CommandLineOptions.Clo.DoBitVectorAnalysis)
- {
+ if (CommandLineOptions.Clo.DoBitVectorAnalysis) {
Microsoft.Boogie.BitVectorAnalysis.DoBitVectorAnalysis(program);
PrintBplFile(CommandLineOptions.Clo.BitVectorAnalysisOutputBplFile, program, false);
return;
}
- if (CommandLineOptions.Clo.PrintCFGPrefix != null)
- {
- foreach (var impl in program.TopLevelDeclarations.OfType<Implementation>())
- {
- using (StreamWriter sw = new StreamWriter(CommandLineOptions.Clo.PrintCFGPrefix + "." + impl.Name + ".dot"))
- {
+ if (CommandLineOptions.Clo.PrintCFGPrefix != null) {
+ foreach (var impl in program.TopLevelDeclarations.OfType<Implementation>()) {
+ using (StreamWriter sw = new StreamWriter(CommandLineOptions.Clo.PrintCFGPrefix + "." + impl.Name + ".dot")) {
sw.Write(program.ProcessLoops(impl).ToDot());
}
}
@@ -227,8 +219,7 @@ namespace Microsoft.Boogie
int errorCount, verified, inconclusives, timeOuts, outOfMemories;
oc = InferAndVerify(program, out errorCount, out verified, out inconclusives, out timeOuts, out outOfMemories);
- switch (oc)
- {
+ switch (oc) {
case PipelineOutcome.Done:
case PipelineOutcome.VerificationCompleted:
WriteTrailer(verified, errorCount, inconclusives, timeOuts, outOfMemories);
@@ -240,21 +231,17 @@ namespace Microsoft.Boogie
}
- static void PrintBplFile(string filename, Program program, bool allowPrintDesugaring)
- {
+ static void PrintBplFile(string filename, Program program, bool allowPrintDesugaring) {
Contract.Requires(program != null);
Contract.Requires(filename != null);
bool oldPrintDesugaring = CommandLineOptions.Clo.PrintDesugarings;
- if (!allowPrintDesugaring)
- {
+ if (!allowPrintDesugaring) {
CommandLineOptions.Clo.PrintDesugarings = false;
}
using (TokenTextWriter writer = filename == "-" ?
new TokenTextWriter("<console>", Console.Out) :
- new TokenTextWriter(filename))
- {
- if (CommandLineOptions.Clo.ShowEnv != CommandLineOptions.ShowEnvironment.Never)
- {
+ new TokenTextWriter(filename)) {
+ if (CommandLineOptions.Clo.ShowEnv != CommandLineOptions.ShowEnvironment.Never) {
writer.WriteLine("// " + CommandLineOptions.Clo.Version);
writer.WriteLine("// " + CommandLineOptions.Clo.Environment);
}
@@ -265,71 +252,39 @@ namespace Microsoft.Boogie
}
- static bool ProgramHasDebugInfo(Program program)
- {
+ static bool ProgramHasDebugInfo(Program program) {
Contract.Requires(program != null);
// We inspect the last declaration because the first comes from the prelude and therefore always has source context.
return program.TopLevelDeclarations.Count > 0 &&
((cce.NonNull(program.TopLevelDeclarations)[program.TopLevelDeclarations.Count - 1]).tok.IsValid);
}
- static QKeyValue GetAttributes(Absy a)
- {
- if (a is PredicateCmd)
- {
- return (a as PredicateCmd).Attributes;
- }
- else if (a is Requires)
- {
- return (a as Requires).Attributes;
- }
- else if (a is Ensures)
- {
- return (a as Ensures).Attributes;
- }
- else if (a is CallCmd)
- {
- return (a as CallCmd).Attributes;
- }
- //Debug.Assert(false);
- return null;
- }
/// <summary>
/// Inform the user about something and proceed with translation normally.
/// Print newline after the message.
/// </summary>
- public static void Inform(string s)
- {
- if (!CommandLineOptions.Clo.Trace)
- {
- return;
+ public static void Inform(string s) {
+ if (CommandLineOptions.Clo.Trace || CommandLineOptions.Clo.TraceProofObligations) {
+ Console.WriteLine(s);
}
- Console.WriteLine(s);
}
- static void WriteTrailer(int verified, int errors, int inconclusives, int timeOuts, int outOfMemories)
- {
+ static void WriteTrailer(int verified, int errors, int inconclusives, int timeOuts, int outOfMemories) {
Contract.Requires(0 <= errors && 0 <= inconclusives && 0 <= timeOuts && 0 <= outOfMemories);
Console.WriteLine();
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed)
- {
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
Console.Write("{0} finished with {1} credible, {2} doomed{3}", CommandLineOptions.Clo.DescriptiveToolName, verified, errors, errors == 1 ? "" : "s");
- }
- else
- {
+ } else {
Console.Write("{0} finished with {1} verified, {2} error{3}", CommandLineOptions.Clo.DescriptiveToolName, verified, errors, errors == 1 ? "" : "s");
}
- if (inconclusives != 0)
- {
+ if (inconclusives != 0) {
Console.Write(", {0} inconclusive{1}", inconclusives, inconclusives == 1 ? "" : "s");
}
- if (timeOuts != 0)
- {
+ if (timeOuts != 0) {
Console.Write(", {0} time out{1}", timeOuts, timeOuts == 1 ? "" : "s");
}
- if (outOfMemories != 0)
- {
+ if (outOfMemories != 0) {
Console.Write(", {0} out of memory", outOfMemories);
}
Console.WriteLine();
@@ -340,17 +295,13 @@ namespace Microsoft.Boogie
static void ReportBplError(Absy node, string message, bool error, bool showBplLocation)
{
- int failLine = -1;
- int failCol = -1;
- string failFile = null;
- string locinfo = null;
+ int failLine = -1, failCol = -1;
+ string failFile = null, locinfo = null;
QKeyValue attrs = GetAttributes(node);
if (node != null)
{
- failLine = QKeyValue.FindIntAttribute(attrs, "line", -1);
- failCol = QKeyValue.FindIntAttribute(attrs, "col", -1);
- failFile = QKeyValue.FindStringAttribute(attrs, "fname");
+ GetLocInfoFromAttrs(attrs, out failLine, out failCol, out failFile);
}
if (showBplLocation && failLine != -1 && failCol != -1 && failFile != null)
@@ -384,72 +335,54 @@ namespace Microsoft.Boogie
/// Parse the given files into one Boogie program. If an I/O or parse error occurs, an error will be printed
/// and null will be returned. On success, a non-null program is returned.
/// </summary>
- static Program ParseBoogieProgram(List<string> fileNames, bool suppressTraceOutput)
- {
+ static Program ParseBoogieProgram(List<string> fileNames, bool suppressTraceOutput) {
Contract.Requires(cce.NonNullElements(fileNames));
//BoogiePL.Errors.count = 0;
Program program = null;
bool okay = true;
- for (int fileId = 0; fileId < fileNames.Count; fileId++)
- {
+ for (int fileId = 0; fileId < fileNames.Count; fileId++) {
string bplFileName = fileNames[fileId];
- if (!suppressTraceOutput)
- {
- if (CommandLineOptions.Clo.XmlSink != null)
- {
+ if (!suppressTraceOutput) {
+ if (CommandLineOptions.Clo.XmlSink != null) {
CommandLineOptions.Clo.XmlSink.WriteFileFragment(bplFileName);
}
- if (CommandLineOptions.Clo.Trace)
- {
+ if (CommandLineOptions.Clo.Trace) {
Console.WriteLine("Parsing " + bplFileName);
}
}
Program programSnippet;
int errorCount;
- try
- {
+ try {
var defines = new List<string>() { "FILE_" + fileId };
errorCount = BoogiePL.Parser.Parse(bplFileName, defines, out programSnippet);
- if (programSnippet == null || errorCount != 0)
- {
+ if (programSnippet == null || errorCount != 0) {
Console.WriteLine("{0} parse errors detected in {1}", errorCount, bplFileName);
okay = false;
continue;
}
- }
- catch (IOException e)
- {
+ } catch (IOException e) {
ErrorWriteLine("Error opening file \"{0}\": {1}", bplFileName, e.Message);
okay = false;
continue;
}
- if (program == null)
- {
+ if (program == null) {
program = programSnippet;
- }
- else if (programSnippet != null)
- {
+ } else if (programSnippet != null) {
program.TopLevelDeclarations.AddRange(programSnippet.TopLevelDeclarations);
}
}
- if (!okay)
- {
+ if (!okay) {
return null;
- }
- else if (program == null)
- {
+ } else if (program == null) {
return new Program();
- }
- else
- {
+ } else {
return program;
}
}
- enum PipelineOutcome
- {
+ enum PipelineOutcome {
Done,
ResolutionError,
TypeCheckingError,
@@ -466,40 +399,34 @@ namespace Microsoft.Boogie
/// - TypeCheckingError if a type checking error occurred
/// - ResolvedAndTypeChecked if both resolution and type checking succeeded
/// </summary>
- static PipelineOutcome ResolveAndTypecheck(Program program, string bplFileName)
- {
+ static PipelineOutcome ResolveAndTypecheck(Program program, string bplFileName) {
Contract.Requires(program != null);
Contract.Requires(bplFileName != null);
// ---------- Resolve ------------------------------------------------------------
- if (CommandLineOptions.Clo.NoResolve)
- {
+ if (CommandLineOptions.Clo.NoResolve) {
return PipelineOutcome.Done;
}
int errorCount = program.Resolve();
- if (errorCount != 0)
- {
+ if (errorCount != 0) {
Console.WriteLine("{0} name resolution errors detected in {1}", errorCount, bplFileName);
return PipelineOutcome.ResolutionError;
}
// ---------- Type check ------------------------------------------------------------
- if (CommandLineOptions.Clo.NoTypecheck)
- {
+ if (CommandLineOptions.Clo.NoTypecheck) {
return PipelineOutcome.Done;
}
errorCount = program.Typecheck();
- if (errorCount != 0)
- {
+ if (errorCount != 0) {
Console.WriteLine("{0} type checking errors detected in {1}", errorCount, bplFileName);
return PipelineOutcome.TypeCheckingError;
}
- if (CommandLineOptions.Clo.PrintFile != null && CommandLineOptions.Clo.PrintDesugarings)
- {
+ if (CommandLineOptions.Clo.PrintFile != null && CommandLineOptions.Clo.PrintDesugarings) {
// if PrintDesugaring option is engaged, print the file here, after resolution and type checking
PrintBplFile(CommandLineOptions.Clo.PrintFile, program, true);
}
@@ -507,21 +434,18 @@ namespace Microsoft.Boogie
return PipelineOutcome.ResolvedAndTypeChecked;
}
- static void EliminateDeadVariablesAndInline(Program program)
- {
+ static void EliminateDeadVariablesAndInline(Program program) {
Contract.Requires(program != null);
// Eliminate dead variables
Microsoft.Boogie.UnusedVarEliminator.Eliminate(program);
// Collect mod sets
- if (CommandLineOptions.Clo.DoModSetAnalysis)
- {
+ if (CommandLineOptions.Clo.DoModSetAnalysis) {
Microsoft.Boogie.ModSetCollector.DoModSetAnalysis(program);
}
// Coalesce blocks
- if (CommandLineOptions.Clo.CoalesceBlocks)
- {
+ if (CommandLineOptions.Clo.CoalesceBlocks) {
if (CommandLineOptions.Clo.Trace)
Console.WriteLine("Coalescing blocks...");
Microsoft.Boogie.BlockCoalescer.CoalesceBlocks(program);
@@ -530,40 +454,30 @@ namespace Microsoft.Boogie
// Inline
var TopLevelDeclarations = cce.NonNull(program.TopLevelDeclarations);
- if (CommandLineOptions.Clo.ProcedureInlining != CommandLineOptions.Inlining.None)
- {
+ if (CommandLineOptions.Clo.ProcedureInlining != CommandLineOptions.Inlining.None) {
bool inline = false;
- foreach (var d in TopLevelDeclarations)
- {
- if (d.FindExprAttribute("inline") != null)
- {
+ foreach (var d in TopLevelDeclarations) {
+ if (d.FindExprAttribute("inline") != null) {
inline = true;
}
}
- if (inline)
- {
- foreach (var d in TopLevelDeclarations)
- {
+ if (inline) {
+ foreach (var d in TopLevelDeclarations) {
var impl = d as Implementation;
- if (impl != null)
- {
+ if (impl != null) {
impl.OriginalBlocks = impl.Blocks;
impl.OriginalLocVars = impl.LocVars;
}
}
- foreach (var d in TopLevelDeclarations)
- {
+ foreach (var d in TopLevelDeclarations) {
var impl = d as Implementation;
- if (impl != null && !impl.SkipVerification)
- {
+ if (impl != null && !impl.SkipVerification) {
Inliner.ProcessImplementation(program, impl);
}
}
- foreach (var d in TopLevelDeclarations)
- {
+ foreach (var d in TopLevelDeclarations) {
var impl = d as Implementation;
- if (impl != null)
- {
+ if (impl != null) {
impl.OriginalBlocks = null;
impl.OriginalLocVars = null;
}
@@ -572,171 +486,9 @@ namespace Microsoft.Boogie
}
}
- static QKeyValue ExtractAsertSourceLocFromTrace(BlockSeq s)
- {
- foreach (Block b in s)
- {
- foreach (Cmd c in b.Cmds)
- {
- if (c is AssertCmd)
- {
- if (QKeyValue.FindBoolAttribute(((AssertCmd)c).Attributes, "sourceloc"))
- {
- return ((AssertCmd)c).Attributes;
- }
- }
- }
- }
- return null;
- }
-
- static QKeyValue CreateSourceLocQKV(int line, int col, string fname, string dir)
- {
- QKeyValue dirkv = new QKeyValue(Token.NoToken, "dir", new List<object>(new object[] { dir }), null);
- QKeyValue fnamekv = new QKeyValue(Token.NoToken, "fname", new List<object>(new object[] { fname }), dirkv);
- QKeyValue colkv = new QKeyValue(Token.NoToken, "col", new List<object>(new object[] { new LiteralExpr(Token.NoToken, BigNum.FromInt(col)) }), fnamekv);
- QKeyValue linekv = new QKeyValue(Token.NoToken, "line", new List<object>(new object[] { new LiteralExpr(Token.NoToken, BigNum.FromInt(line)) }), colkv);
- return linekv;
- }
-
- static QKeyValue GetSourceLocInfo(Counterexample error, string AccessType) {
- string sourceVarName = null;
- int sourceLocLineNo = -1;
-
- string sourceLocFileName = Path.GetDirectoryName(CommandLineOptions.Clo.Files[0]) +
- Path.DirectorySeparatorChar +
- Path.GetFileNameWithoutExtension(CommandLineOptions.Clo.Files[0]) +
- ".loc";
-
- TextReader tr = new StreamReader(sourceLocFileName);
-
- foreach (Block b in error.Trace)
- {
- foreach (Cmd c in b.Cmds)
- {
- if (b.tok.val.Equals("_LOG_" + AccessType) && c.ToString().Contains(AccessType + "_SOURCE_"))
- {
- sourceVarName = Regex.Split(c.ToString(), " ")[1];
- }
- }
- }
- if (sourceVarName != null)
- {
- Model.Func f = error.Model.TryGetFunc(sourceVarName);
- if (f != null)
- {
- sourceLocLineNo = f.GetConstant().AsInt();
- }
- }
-
- if (sourceLocLineNo != 0 && sourceLocLineNo != -1)
- {
- string fileLine;
- int currLineNo;
- for(currLineNo = 0; ((fileLine = tr.ReadLine()) != null); currLineNo++)
- {
- if (currLineNo == sourceLocLineNo)
- {
- break;
- }
- }
- if (currLineNo < sourceLocLineNo)
- {
- fileLine = null;
- Console.WriteLine("sourceLocLineNo greater than number of lines in .loc file ({0} > {1})\n", sourceLocLineNo, (currLineNo + 1));
- return null;
- }
- if (fileLine != null)
- {
- string[] slocTokens = Regex.Split(fileLine, "#");
- return CreateSourceLocQKV(
- System.Convert.ToInt32(slocTokens[0]),
- System.Convert.ToInt32(slocTokens[1]),
- slocTokens[2],
- slocTokens[3]);
- }
- }
- else
- {
- Console.WriteLine("sourceLocLineNo is {0}. No sourceloc at that location.\n", sourceLocLineNo);
- return null;
- }
- tr.Close();
- return null;
- }
-
- static bool IsRepeatedKV(QKeyValue attrs, List<QKeyValue> alreadySeen)
- {
- //return false;
- if (attrs == null)
- {
- return false;
- }
- string key = null;
- foreach (QKeyValue qkv in alreadySeen)
- {
- QKeyValue kv = qkv.Clone() as QKeyValue;
- if (kv.Params.Count != attrs.Params.Count)
- {
- return false;
- }
- for (; kv != null; kv = kv.Next) {
- key = kv.Key;
- if (key != "thread") {
- if (kv.Params.Count == 0)
- {
- if (QKeyValue.FindBoolAttribute(attrs, key))
- {
- continue;
- }
- else
- {
- return false;
- }
-
- }
- else if (kv.Params[0] is LiteralExpr)
- { // int
- LiteralExpr l = kv.Params[0] as LiteralExpr;
- int i = l.asBigNum.ToIntSafe;
- if (QKeyValue.FindIntAttribute(attrs, key, -1) == i)
- {
- continue;
- }
- else
- {
- return false;
- }
- }
- else if (kv.Params[0] is string)
- { // string
- string s = kv.Params[0] as string;
- if (QKeyValue.FindStringAttribute(attrs, key) == s)
- {
- continue;
- }
- else
- {
- return false;
- }
- }
- else
- {
- Debug.Assert(false);
- return false;
- }
- }
- }
- return true;
- }
- return false;
- }
-
static void ProcessOutcome(VC.VCGen.Outcome outcome, List<Counterexample> errors, string timeIndication,
- ref int errorCount, ref int verified, ref int inconclusives, ref int timeOuts, ref int outOfMemories)
- {
- switch (outcome)
- {
+ ref int errorCount, ref int verified, ref int inconclusives, ref int timeOuts, ref int outOfMemories) {
+ switch (outcome) {
default:
Contract.Assert(false); // unexpected outcome
throw new cce.UnreachableException();
@@ -746,13 +498,11 @@ namespace Microsoft.Boogie
verified++;
break;
case VCGen.Outcome.Correct:
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed)
- {
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
Inform(String.Format("{0}credible", timeIndication));
verified++;
}
- else
- {
+ else {
Inform(String.Format("{0}verified", timeIndication));
verified++;
}
@@ -770,8 +520,7 @@ namespace Microsoft.Boogie
Inform(String.Format("{0}inconclusive", timeIndication));
break;
case VCGen.Outcome.Errors:
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed)
- {
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
Inform(String.Format("{0}doomed", timeIndication));
errorCount++;
} //else {
@@ -784,210 +533,105 @@ namespace Microsoft.Boogie
// BP5xxx: Verification errors
errors.Sort(new CounterexampleComparer());
- List<QKeyValue> seenAssertAttrs = new List<QKeyValue>();
- List<QKeyValue> seenReqAttrs = new List<QKeyValue>();
- List<QKeyValue> seenEnsAttrs = new List<QKeyValue>();
- List<QKeyValue> seenInvEAttrs = new List<QKeyValue>();
- List<QKeyValue> seenInvMAttrs = new List<QKeyValue>();
- List<QKeyValue> seenWWRaceAttrs = new List<QKeyValue>();
- List<QKeyValue> seenWRRaceAttrs = new List<QKeyValue>();
- List<QKeyValue> seenRWRaceAttrs = new List<QKeyValue>();
- bool incrementErrors = true;
foreach (Counterexample error in errors)
{
if (error is CallCounterexample)
{
CallCounterexample err = (CallCounterexample)error;
- if (!CommandLineOptions.Clo.ForceBplErrors && err.FailingRequires.ErrorMessage != null)
- {
- ReportBplError(err.FailingRequires, err.FailingRequires.ErrorMessage, true, false);
- }
- else if (QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "barrier_divergence"))
+ if (QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "barrier_divergence"))
{
- ReportBplError(err.FailingCall, "Barrier Divergence Error: \nThe following barrier is reached by non-uniform control flow:", true, true);
+ ReportBarrierDivergence(err.FailingCall);
}
else if (QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "race"))
- {
- int lidx1 = -1, lidy1 = -1, lidz1 = -1, lidx2 = -1, lidy2 = -1, lidz2 = -1;
- int gidx1 = -1, gidy1 = -1, gidz1 = -1, gidx2 = -1, gidy2 = -1, gidz2 = -1;
- string thread1 = null, thread2 = null, group1 = null, group2 = null;
- if (error.Model != null)
- {
- lidx1 = error.Model.TryGetFunc("local_id_x$1").GetConstant().AsInt();
- lidy1 = error.Model.TryGetFunc("local_id_y$1").GetConstant().AsInt();
- lidz1 = error.Model.TryGetFunc("local_id_z$1").GetConstant().AsInt();
- lidx2 = error.Model.TryGetFunc("local_id_x$2").GetConstant().AsInt();
- lidy2 = error.Model.TryGetFunc("local_id_y$2").GetConstant().AsInt();
- lidz2 = error.Model.TryGetFunc("local_id_z$2").GetConstant().AsInt();
-
- gidx1 = error.Model.TryGetFunc("group_id_x$1").GetConstant().AsInt();
- gidy1 = error.Model.TryGetFunc("group_id_y$1").GetConstant().AsInt();
- gidz1 = error.Model.TryGetFunc("group_id_z$1").GetConstant().AsInt();
- gidx2 = error.Model.TryGetFunc("group_id_x$2").GetConstant().AsInt();
- gidy2 = error.Model.TryGetFunc("group_id_y$2").GetConstant().AsInt();
- gidz2 = error.Model.TryGetFunc("group_id_z$2").GetConstant().AsInt();
-
- thread1 = "(" + lidx1 + ", " + lidy1 + ", " + lidz1 + ")";
- thread2 = "(" + lidx2 + ", " + lidy2 + ", " + lidz2 + ")";
-
- group1 = "(" + gidx1 + ", " + gidy1 + ", " + gidz1 + ")";
- group2 = "(" + gidx2 + ", " + gidy2 + ", " + gidz2 + ")";
- }
+ {
+ int byteOffset = -1, elemOffset = -1, elemWidth = -1;
+ string thread1 = null, thread2 = null, group1 = null, group2 = null, arrName = null;
+ //TODO: make this a command line argument.
+ bool detailedTrace = false;
+ string threadOneFailAccess = null, threadTwoFailAccess = null;
+
+ Variable offsetVar = ExtractOffsetVar(err.FailingRequires.Condition as NAryExpr);
+ /* Right now the offset incarnation that is extracted is the penultimate one if
+ * there is more than one incarnation, or the last one if there is only one incarnation.
+ * TODO: In future, we should know the exact incarnation to extract. This information is
+ * available when the CallCounterexample is created in VC.cs AssertCmdToCounterexample() (line 2405)
+ * The condition of the AssertRequiresCmd contains the incarnation information, so this should be passed
+ * on to the Requires of the created CallCounterexample. This can either be done by replacing the condition
+ * of the Requires with the condition from AssertRequiresCmd (containing incarnation information) or creating
+ * a separate field in the Requires to store this original condition.
+ */
+ Model.Func offsetFunc = ExtractIncarnationFromModel(error.Model, offsetVar.Name);
+ Debug.Assert(offsetFunc != null, "ProcessOutcome(): Could not extract incarnation.");
+ GetInfoFromVarAndFunc(offsetVar.Attributes, offsetFunc, out byteOffset, out elemOffset, out elemWidth, out arrName);
+
+ Debug.Assert(error.Model != null, "ProcessOutcome(): null model");
+ GetThreadsAndGroupsFromModel(err.Model, out thread1, out thread2, out group1, out group2, true);
+
if (QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "write_read"))
{
err.FailingRequires.Attributes = GetSourceLocInfo(error, "WRITE");
- ReportBplError(err.FailingCall, "Race Error: Write-read race caused by \nthread "
- + thread2 + ", group " + group2 + " executing statement at:" , true, true);
- ReportBplError(err.FailingRequires, "The conflicting statement executed by thread "
- + thread1 + ", group " + group1 + " is:", true, true);
+ threadOneFailAccess = "WRITE";
+ threadTwoFailAccess = "READ";
+ ReportRace(err.FailingCall, err.FailingRequires, thread1, thread2, group1, group2, arrName, byteOffset, RaceType.WR);
}
else if (QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "read_write"))
{
err.FailingRequires.Attributes = GetSourceLocInfo(error, "READ");
- ReportBplError(err.FailingCall, "Race Error: Read-write race caused by \nthread "
- + thread2 + ", group " + group2 + " executing statement at:", true, true);
- ReportBplError(err.FailingRequires, "The conflicting statement executed by thread "
- + thread1 + ", group " + group1 + " is:", true, true);
+ threadOneFailAccess = "READ";
+ threadTwoFailAccess = "WRITE";
+ ReportRace(err.FailingCall, err.FailingRequires, thread1, thread2, group1, group2, arrName, byteOffset, RaceType.RW);
}
else if (QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "write_write"))
{
err.FailingRequires.Attributes = GetSourceLocInfo(error, "WRITE");
- ReportBplError(err.FailingCall, "Race Error: Write-write race caused by \nthread "
- + thread2 + ", group " + group2 + " executing statement at:", true, true);
- ReportBplError(err.FailingRequires, "The conflicting statement executed by thread "
- + thread1 + ", group " + group1 + " is:", true, true);
-
+ threadOneFailAccess = "WRITE";
+ threadTwoFailAccess = "WRITE";
+ ReportRace(err.FailingCall, err.FailingRequires, thread1, thread2, group1, group2, arrName, byteOffset, RaceType.WW);
}
- }
- else
- {
- if (!IsRepeatedKV(err.FailingRequires.Attributes, seenReqAttrs))
- {
- ReportBplError(err.FailingCall, "Requires Error: A precondition for this call might not hold:", true, true);
- ReportBplError(err.FailingRequires, "Related location: This is the precondition that might not hold:", false, true);
- seenReqAttrs.Add(err.FailingRequires.Attributes);
- }
- else
+
+ if (detailedTrace)
{
- incrementErrors = false;
+ string fname = QKeyValue.FindStringAttribute(err.FailingCall.Attributes, "fname");
+ Debug.Assert(!String.IsNullOrEmpty(fname));
+ int colOneSize = fname.Length + 11;
+ string colTwoHeader = " T " + GetThreadOne(error.Model, false) + " G " + GetGroupOne(error.Model, false) + " ";
+ string colThreeHeader = " T " + GetThreadTwo(error.Model, false) + " G " + GetGroupTwo(error.Model, false) + " ";
+
+ int colTwoSize = colTwoHeader.Length + 2;
+ int colThreeSize = colTwoHeader.Length + 2;
+
+ PrintDetailedTraceHeader(colTwoHeader, colThreeHeader, colOneSize, colTwoSize, colThreeSize);
+ PrintDetailedTrace(err, colOneSize, colTwoSize, colThreeSize, elemOffset, elemWidth, threadOneFailAccess, threadTwoFailAccess);
}
}
- if (CommandLineOptions.Clo.XmlSink != null)
+ else
{
- CommandLineOptions.Clo.XmlSink.WriteError("precondition violation", err.FailingCall.tok, err.FailingRequires.tok, error.Trace);
+ ReportRequiresFailure(err.FailingCall, err.FailingRequires);
}
}
else if (error is ReturnCounterexample)
{
ReturnCounterexample err = (ReturnCounterexample)error;
- if (!CommandLineOptions.Clo.ForceBplErrors && err.FailingEnsures.ErrorMessage != null)
- {
- ReportBplError(err.FailingEnsures, err.FailingEnsures.ErrorMessage, true, false);
- }
- else
- {
- if (!IsRepeatedKV(err.FailingEnsures.Attributes, seenEnsAttrs)) {
- ReportBplError(err.FailingEnsures, "Ensures Error: This postcondition might not hold on all return paths:", true, true);
- seenEnsAttrs.Add(err.FailingEnsures.Attributes);
- }
- else
- {
- incrementErrors = false;
- }
- }
- if (CommandLineOptions.Clo.XmlSink != null)
- {
- CommandLineOptions.Clo.XmlSink.WriteError("postcondition violation", err.FailingReturn.tok, err.FailingEnsures.tok, error.Trace);
- }
+ ReportEnsuresFailure(err.FailingEnsures);
}
- else // error is AssertCounterexample
+ else
{
AssertCounterexample err = (AssertCounterexample)error;
if (err.FailingAssert is LoopInitAssertCmd)
{
- if (!IsRepeatedKV(err.FailingAssert.Attributes, seenInvEAttrs)) {
- ReportBplError(err.FailingAssert, "Invariant Error: This loop invariant might not hold on entry:", true, true);
- if (CommandLineOptions.Clo.XmlSink != null)
- {
- CommandLineOptions.Clo.XmlSink.WriteError("loop invariant entry violation", err.FailingAssert.tok, null, error.Trace);
- }
- seenInvEAttrs.Add(err.FailingAssert.Attributes);
- }
- else
- {
- incrementErrors = false;
- }
+ ReportInvariantEntryFailure(err.FailingAssert);
}
else if (err.FailingAssert is LoopInvMaintainedAssertCmd)
{
- // this assertion is a loop invariant which is not maintained
- if (!IsRepeatedKV(err.FailingAssert.Attributes, seenInvMAttrs)) {
- ReportBplError(err.FailingAssert, "Invariant Error: This loop invariant might not be maintained by the loop:", true, true);
- if (CommandLineOptions.Clo.XmlSink != null)
- {
- CommandLineOptions.Clo.XmlSink.WriteError("loop invariant maintenance violation", err.FailingAssert.tok, null, error.Trace);
- }
- seenInvMAttrs.Add(err.FailingAssert.Attributes);
- }
- else
- {
- incrementErrors = false;
- }
+ ReportInvariantMaintedFailure(err.FailingAssert);
}
else
{
- if (!CommandLineOptions.Clo.ForceBplErrors && err.FailingAssert.ErrorMessage != null)
- {
- ReportBplError(err.FailingAssert, err.FailingAssert.ErrorMessage, true, false);
- }
- else if (err.FailingAssert.ErrorData is string)
- {
- ReportBplError(err.FailingAssert, (string)err.FailingAssert.ErrorData, true, true);
- }
- else
- {
- if (!IsRepeatedKV(err.FailingAssert.Attributes, seenAssertAttrs))
- {
- ReportBplError(err.FailingAssert, "Assertion Error: This assertion might not hold:", true, true);
- seenAssertAttrs.Add(err.FailingAssert.Attributes.Clone() as QKeyValue);
- }
- else
- {
- incrementErrors = false;
- }
- }
- if (CommandLineOptions.Clo.XmlSink != null)
- {
- CommandLineOptions.Clo.XmlSink.WriteError("assertion violation", err.FailingAssert.tok, null, error.Trace);
- }
+ ReportFailingAssert(err.FailingAssert);
}
}
- if (CommandLineOptions.Clo.EnhancedErrorMessages == 1)
- {
- foreach (string info in error.relatedInformation)
- {
- Contract.Assert(info != null);
- Console.WriteLine(" " + info);
- }
- }
- /* Get rid of this, as we are only using /enhancedErrorMessages to pass the model through.
- * We don't actually want to see the enhanced error messages.
- *
- if (CommandLineOptions.Clo.ErrorTrace > 0)
- {
- Console.WriteLine("Execution trace:");
- error.Print(4);
- }
- */
- if (CommandLineOptions.Clo.ModelViewFile != null)
- {
- error.PrintModel();
- }
- if (incrementErrors)
- {
- errorCount++;
- }
+ errorCount++;
}
//}
Inform(String.Format("{0}error{1}", timeIndication, errors.Count == 1 ? "" : "s"));
@@ -996,6 +640,33 @@ namespace Microsoft.Boogie
}
}
+ private static void PrintDetailedTraceHeader(string colTwoHeader, string colThreeHeader, int locationColSize, int colTwoSize, int colThreeSize)
+ {
+ Console.Write("\nLocation");
+ PrintNChars(locationColSize - "Location".Length, ' ');
+ Console.WriteLine("|{0}|{1}", colTwoHeader + Chars(colTwoSize - colTwoHeader.Length, ' '), colThreeHeader + Chars(colThreeSize - colThreeHeader.Length, ' '));
+ PrintNChars(locationColSize, '-');
+ Console.Write("|");
+ PrintNChars(colTwoSize, '-');
+ Console.Write("|");
+ PrintNChars(colThreeSize, '-');
+ Console.WriteLine("");
+ }
+
+ private static void PrintNChars(int n, char c)
+ {
+ for (int i = 0; i < n; ++i)
+ {
+ Console.Write(c);
+ }
+ }
+
+ private static string Chars(int n, char c)
+ {
+ return new String(c, n);
+ }
+
+
/// <summary>
/// Given a resolved and type checked Boogie program, infers invariants for the program
/// and then attempts to verify it. Returns:
@@ -1005,8 +676,7 @@ namespace Microsoft.Boogie
/// parameters contain meaningful values
/// </summary>
static PipelineOutcome InferAndVerify(Program program,
- out int errorCount, out int verified, out int inconclusives, out int timeOuts, out int outOfMemories)
- {
+ out int errorCount, out int verified, out int inconclusives, out int timeOuts, out int outOfMemories) {
Contract.Requires(program != null);
Contract.Ensures(0 <= Contract.ValueAtReturn(out inconclusives) && 0 <= Contract.ValueAtReturn(out timeOuts));
@@ -1015,27 +685,22 @@ namespace Microsoft.Boogie
// ---------- Infer invariants --------------------------------------------------------
// Abstract interpretation -> Always use (at least) intervals, if not specified otherwise (e.g. with the "/noinfer" switch)
- if (CommandLineOptions.Clo.Ai.J_Intervals || CommandLineOptions.Clo.Ai.J_Trivial)
- {
- Microsoft.Boogie.AbstractInterpretation.NativeAbstractInterpretation.RunAbstractInterpretation(program);
- }
- else
- {
- Microsoft.Boogie.AbstractInterpretation.AbstractInterpretation.RunAbstractInterpretation(program);
+ if (CommandLineOptions.Clo.UseAbstractInterpretation) {
+ if (!CommandLineOptions.Clo.Ai.J_Intervals && !CommandLineOptions.Clo.Ai.J_Trivial) {
+ // use /infer:j as the default
+ CommandLineOptions.Clo.Ai.J_Intervals = true;
+ }
}
+ Microsoft.Boogie.AbstractInterpretation.NativeAbstractInterpretation.RunAbstractInterpretation(program);
- if (CommandLineOptions.Clo.LoopUnrollCount != -1)
- {
+ if (CommandLineOptions.Clo.LoopUnrollCount != -1) {
program.UnrollLoops(CommandLineOptions.Clo.LoopUnrollCount);
}
- if (CommandLineOptions.Clo.DoPredication && CommandLineOptions.Clo.StratifiedInlining > 0)
- {
+ if (CommandLineOptions.Clo.DoPredication && CommandLineOptions.Clo.StratifiedInlining > 0) {
BlockPredicator.Predicate(program, false, false);
- if (CommandLineOptions.Clo.PrintInstrumented)
- {
- using (TokenTextWriter writer = new TokenTextWriter(Console.Out))
- {
+ if (CommandLineOptions.Clo.PrintInstrumented) {
+ using (TokenTextWriter writer = new TokenTextWriter(Console.Out)) {
program.Emit(writer);
}
}
@@ -1047,42 +712,35 @@ namespace Microsoft.Boogie
extractLoopMappingInfo = program.ExtractLoops();
}
- if (CommandLineOptions.Clo.PrintInstrumented)
- {
+ if (CommandLineOptions.Clo.PrintInstrumented) {
program.Emit(new TokenTextWriter(Console.Out));
}
- if (CommandLineOptions.Clo.ExpandLambdas)
- {
+ if (CommandLineOptions.Clo.ExpandLambdas) {
LambdaHelper.ExpandLambdas(program);
//PrintBplFile ("-", program, true);
}
// ---------- Verify ------------------------------------------------------------
- if (!CommandLineOptions.Clo.Verify)
- {
+ if (!CommandLineOptions.Clo.Verify) {
return PipelineOutcome.Done;
}
#region Run Houdini and verify
- if (CommandLineOptions.Clo.ContractInfer)
- {
+ if (CommandLineOptions.Clo.ContractInfer) {
Houdini.Houdini houdini = new Houdini.Houdini(program);
Houdini.HoudiniOutcome outcome = houdini.PerformHoudiniInference();
- if (CommandLineOptions.Clo.PrintAssignment)
- {
+ if (CommandLineOptions.Clo.PrintAssignment) {
Console.WriteLine("Assignment computed by Houdini:");
- foreach (var x in outcome.assignment)
- {
+ foreach (var x in outcome.assignment) {
Console.WriteLine(x.Key + " = " + x.Value);
}
}
if (CommandLineOptions.Clo.Trace)
{
int numTrueAssigns = 0;
- foreach (var x in outcome.assignment)
- {
+ foreach (var x in outcome.assignment) {
if (x.Value)
numTrueAssigns++;
}
@@ -1095,8 +753,7 @@ namespace Microsoft.Boogie
Console.WriteLine("Number of unsat core prunings = " + Houdini.HoudiniSession.numUnsatCorePrunings);
}
- foreach (Houdini.VCGenOutcome x in outcome.implementationOutcomes.Values)
- {
+ foreach (Houdini.VCGenOutcome x in outcome.implementationOutcomes.Values) {
ProcessOutcome(x.outcome, x.errors, "", ref errorCount, ref verified, ref inconclusives, ref timeOuts, ref outOfMemories);
}
//errorCount = outcome.ErrorCount;
@@ -1111,63 +768,47 @@ namespace Microsoft.Boogie
#region Verify each implementation
ConditionGeneration vcgen = null;
- try
- {
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed)
- {
+ try {
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
vcgen = new DCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend);
- }
- else if (CommandLineOptions.Clo.StratifiedInlining > 0)
- {
+ } else if(CommandLineOptions.Clo.StratifiedInlining > 0) {
vcgen = new StratifiedVCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend);
- }
- else
- {
+ } else {
vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend);
}
- }
- catch (ProverException e)
- {
+ } catch (ProverException e) {
ErrorWriteLine("Fatal Error: ProverException: {0}", e);
return PipelineOutcome.FatalError;
}
// operate on a stable copy, in case it gets updated while we're running
var decls = program.TopLevelDeclarations.ToArray();
- foreach (Declaration decl in decls)
- {
+ foreach (Declaration decl in decls) {
Contract.Assert(decl != null);
int prevAssertionCount = vcgen.CumulativeAssertionCount;
Implementation impl = decl as Implementation;
- if (impl != null && CommandLineOptions.Clo.UserWantsToCheckRoutine(cce.NonNull(impl.Name)) && !impl.SkipVerification)
- {
+ if (impl != null && CommandLineOptions.Clo.UserWantsToCheckRoutine(cce.NonNull(impl.Name)) && !impl.SkipVerification) {
List<Counterexample/*!*/>/*?*/ errors;
DateTime start = new DateTime(); // to please compiler's definite assignment rules
- if (CommandLineOptions.Clo.Trace || CommandLineOptions.Clo.XmlSink != null)
- {
+ if (CommandLineOptions.Clo.Trace || CommandLineOptions.Clo.TraceProofObligations || CommandLineOptions.Clo.XmlSink != null) {
start = DateTime.UtcNow;
- if (CommandLineOptions.Clo.Trace)
- {
+ if (CommandLineOptions.Clo.Trace || CommandLineOptions.Clo.TraceProofObligations) {
Console.WriteLine();
Console.WriteLine("Verifying {0} ...", impl.Name);
}
- if (CommandLineOptions.Clo.XmlSink != null)
- {
+ if (CommandLineOptions.Clo.XmlSink != null) {
CommandLineOptions.Clo.XmlSink.WriteStartMethod(impl.Name, start);
}
}
VCGen.Outcome outcome;
- try
- {
- if (CommandLineOptions.Clo.inferLeastForUnsat != null)
- {
+ try {
+ if (CommandLineOptions.Clo.inferLeastForUnsat != null) {
var svcgen = vcgen as VC.StratifiedVCGen;
Contract.Assert(svcgen != null);
var ss = new HashSet<string>();
- foreach (var tdecl in program.TopLevelDeclarations)
- {
+ foreach (var tdecl in program.TopLevelDeclarations) {
var c = tdecl as Constant;
if (c == null || !c.Name.StartsWith(CommandLineOptions.Clo.inferLeastForUnsat)) continue;
ss.Add(c.Name);
@@ -1175,32 +816,26 @@ namespace Microsoft.Boogie
outcome = svcgen.FindLeastToVerify(impl, ref ss);
errors = new List<Counterexample>();
Console.Write("Result: ");
- foreach (var s in ss)
- {
+ foreach (var s in ss) {
Console.Write("{0} ", s);
}
Console.WriteLine();
}
- else
- {
+ else {
outcome = vcgen.VerifyImplementation(impl, out errors);
- if (CommandLineOptions.Clo.ExtractLoops && vcgen is VCGen && errors != null)
- {
- for (int i = 0; i < errors.Count; i++)
- {
+ if (CommandLineOptions.Clo.ExtractLoops && vcgen is VCGen && errors != null) {
+ for (int i = 0; i < errors.Count; i++) {
errors[i] = (vcgen as VCGen).extractLoopTrace(errors[i], impl.Name, program, extractLoopMappingInfo);
}
}
}
}
- catch (VCGenException e)
- {
+ catch (VCGenException e) {
ReportBplError(impl, String.Format("Error BP5010: {0} Encountered in implementation {1}.", e.Message, impl.Name), true, true);
errors = null;
outcome = VCGen.Outcome.Inconclusive;
}
- catch (UnexpectedProverOutputException upo)
- {
+ catch (UnexpectedProverOutputException upo) {
AdvisoryWriteLine("Advisory: {0} SKIPPED because of internal error: unexpected prover output: {1}", impl.Name, upo.Message);
errors = null;
outcome = VCGen.Outcome.Inconclusive;
@@ -1209,23 +844,20 @@ namespace Microsoft.Boogie
string timeIndication = "";
DateTime end = DateTime.UtcNow;
TimeSpan elapsed = end - start;
- if (CommandLineOptions.Clo.Trace || CommandLineOptions.Clo.XmlSink != null)
- {
- if (CommandLineOptions.Clo.Trace)
- {
+ if (CommandLineOptions.Clo.Trace) {
+ int poCount = vcgen.CumulativeAssertionCount - prevAssertionCount;
+ timeIndication = string.Format(" [{0:F3} s, {1} proof obligation{2}] ", elapsed.TotalSeconds, poCount, poCount == 1 ? "" : "s");
+ } else if (CommandLineOptions.Clo.TraceProofObligations) {
int poCount = vcgen.CumulativeAssertionCount - prevAssertionCount;
- timeIndication = string.Format(" [{0} s, {1} proof obligation{2}] ", elapsed.ToString("%s\\.fff"), poCount, poCount == 1 ? "" : "s");
- }
+ timeIndication = string.Format(" [{0} proof obligation{1}] ", poCount, poCount == 1 ? "" : "s");
}
ProcessOutcome(outcome, errors, timeIndication, ref errorCount, ref verified, ref inconclusives, ref timeOuts, ref outOfMemories);
- if (CommandLineOptions.Clo.XmlSink != null)
- {
+ if (CommandLineOptions.Clo.XmlSink != null) {
CommandLineOptions.Clo.XmlSink.WriteEndMethod(outcome.ToString().ToLowerInvariant(), end, elapsed);
}
- if (outcome == VCGen.Outcome.Errors || CommandLineOptions.Clo.Trace)
- {
+ if (outcome == VCGen.Outcome.Errors || CommandLineOptions.Clo.Trace) {
Console.Out.Flush();
}
}
@@ -1239,5 +871,767 @@ namespace Microsoft.Boogie
return PipelineOutcome.VerificationCompleted;
}
+
+ private static void AddPadding(ref string string1, ref string string2)
+ {
+ if (string1.Length < string2.Length)
+ {
+ for (int i = (string2.Length - string1.Length); i > 0; --i)
+ {
+ string1 += " ";
+ }
+ }
+ else
+ {
+ for (int i = (string1.Length - string2.Length); i > 0; --i)
+ {
+ string2 += " ";
+ }
+ }
+ }
+
+ private static string TrimLeadingSpaces(string s1, int noOfSpaces)
+ {
+ if (String.IsNullOrWhiteSpace(s1))
+ {
+ return s1;
+ }
+
+ int index;
+ for (index = 0; (index + 1) < s1.Length && Char.IsWhiteSpace(s1[index]); ++index);
+ string returnString = s1.Substring(index);
+ for (int i = noOfSpaces; i > 0; --i)
+ {
+ returnString = " " + returnString;
+ }
+ return returnString;
+ }
+
+ static QKeyValue GetAttributes(Absy a)
+ {
+ if (a is PredicateCmd)
+ {
+ return (a as PredicateCmd).Attributes;
+ }
+ else if (a is Requires)
+ {
+ return (a as Requires).Attributes;
+ }
+ else if (a is Ensures)
+ {
+ return (a as Ensures).Attributes;
+ }
+ else if (a is CallCmd)
+ {
+ return (a as CallCmd).Attributes;
+ }
+ //Debug.Assert(false);
+ return null;
+ }
+
+ static Model.Func ExtractIncarnationFromModel(Model m, string varName)
+ {
+ Model.Func lastFunc = null;
+ Model.Func penulFunc = null;
+ int currIncarnationNo = -1;
+ foreach (Model.Func f in m.Functions)
+ {
+ if(f.Name.Contains(varName))
+ {
+ string[] tokens = Regex.Split(f.Name, "@");
+ if (tokens.Length == 2 && System.Convert.ToInt32(tokens[1]) > currIncarnationNo)
+ {
+ penulFunc = lastFunc;
+ lastFunc = f;
+ currIncarnationNo = System.Convert.ToInt32(tokens[1]);
+ }
+ }
+ }
+ return (penulFunc == null) ? lastFunc : penulFunc;
+ }
+
+ static void PrintDetailedTrace(CallCounterexample err, int colOneLength, int colTwoLength, int colThreeLength, int failElemOffset, int elemWidth, string threadOneFailAccess, string threadTwoFailAccess)
+ {
+ Model model = err.Model;
+ BlockSeq trace = err.Trace;
+
+ int failCallLineNo = QKeyValue.FindIntAttribute(err.FailingCall.Attributes, "line", -1);
+ int failCallColNo = QKeyValue.FindIntAttribute(err.FailingCall.Attributes, "col", -1);
+ int failReqLineNo = QKeyValue.FindIntAttribute(err.FailingRequires.Attributes, "line", -1);
+ int failReqColNo = QKeyValue.FindIntAttribute(err.FailingRequires.Attributes, "col", -1);
+
+ int lineno = -1;
+ int colno = -1;
+
+ bool checkCallExpected = false;
+ bool colTwoFail = false;
+ bool colThreeFail = false;
+
+ string colOne = null;
+ string colTwo = null;
+ string colThree = null;
+
+ foreach (Block b in trace)
+ {
+ if (Regex.IsMatch(b.ToString(), @"inline[$]_LOG_(READ|WRITE)_[$]+\w+[$][0-9]+[$]_LOG_(READ|WRITE)"))
+ {
+ int elemOffset = -1;
+ string arrName;
+
+ foreach (Cmd c in b.Cmds)
+ {
+ string access = (Regex.IsMatch(c.ToString(), @"inline[$]_LOG_READ")) ? "READ" : "WRITE";
+
+ if (Regex.IsMatch(c.ToString(), "assume _" + access + "_OFFSET"))
+ {
+ elemOffset = ExtractOffsetFromExpr(model, (((c as PredicateCmd).Expr as NAryExpr).Args[1] as NAryExpr).Args[1]);
+ }
+ else if (Regex.IsMatch(c.ToString(), "assume _" + access + "_SOURCE"))
+ {
+ arrName = ExtractArrName(c.ToString());
+ string enParamName = ExtractEnabledArg((c as AssumeCmd).Expr).Name;
+
+ Model.Func enFunc = model.TryGetFunc(enParamName);
+ Debug.Assert(enFunc != null, "PrintDetailedTrace(): could not get enParamName from model: " + enParamName);
+ Debug.Assert(enFunc.AppCount == 1, "PrintDetailedTrace(): enabled parameter function has more that one application.");
+ bool enabled = (enFunc.Apps.ElementAt(0).Result as Model.Boolean).Value;
+ int sourceLocLineNo = (ExtractSourceLineArg((c as AssumeCmd).Expr).Val as BvConst).Value.ToIntSafe;
+
+ string sourceLocLine = FetchCodeLine(GetSourceLocFileName(), sourceLocLineNo + 1);
+
+ string[] slocTokens = Regex.Split(sourceLocLine, "#");
+ lineno = System.Convert.ToInt32(slocTokens[0]);
+ colno = System.Convert.ToInt32(slocTokens[1]);
+ string fname = slocTokens[2];
+
+ colOne = fname + ":" + lineno + ":" + colno + ":";
+ colTwo = enabled ? " " + access.ToLower() + "s ((char*)" + arrName + ")" + "[" + ((elemOffset == -1) ? "?" : "" + CalculateByteOffset(elemOffset, elemWidth)) + "]" : "";
+ colTwoFail = elemOffset == failElemOffset && lineno == failReqLineNo && colno == failReqColNo && access == threadOneFailAccess;
+ }
+ }
+ }
+ else if (Regex.IsMatch(b.ToString(), @"inline[$]_LOG_(READ|WRITE)_[$]+\w+[$][0-9]+[$]Return"))
+ {
+ // Assuming that a LOG call will always be immediately followed by a CHECK call.
+ checkCallExpected = true;
+ continue;
+ }
+ else if (checkCallExpected)
+ {
+ foreach (Cmd c in b.Cmds)
+ {
+ if (Regex.IsMatch(c.ToString(), @"assert[\s]+[!]\(\w+[$][0-9]+(@[0-9]+|[\s]+)[\s]*&&[\s]+_(WRITE|READ)_HAS_OCCURRED"))
+ {
+ string access = Regex.IsMatch((c as AssertRequiresCmd).Call.callee, "_CHECK_READ_") ? "READ" : "WRITE";
+
+ string[] tokens = Regex.Split(c.ToString(), "&&");
+ string arrName = ExtractArrName(tokens[1]);
+ string enParamName = ExtractEnabledParameterName((c as AssertRequiresCmd).Expr);
+
+ Model.Func enFunc = model.TryGetFunc(enParamName);
+ Debug.Assert(enFunc != null, "PrintDetailedTrace(): could not get enParamName from model: " + enParamName);
+ Debug.Assert(enFunc.AppCount == 1, "PrintDetailedTrace(): enabled parameter function has more that one application.");
+ bool enabled = (enFunc.Apps.ElementAt(0).Result as Model.Boolean).Value;
+
+ Expr offsetArg = ExtractOffsetArg((c as AssertRequiresCmd).Expr, "_" + (c.ToString().Contains("WRITE") ? "WRITE" : "READ") + "_OFFSET_");
+
+
+
+ int elemOffset = ExtractOffsetFromExpr(model, offsetArg);
+ colThree = enabled ? " " + access.ToLower() + "s ((char*)" + arrName + ")" + "[" + ((elemOffset == -1) ? "?" : "" + CalculateByteOffset(elemOffset, elemWidth)) + "]" : "";
+ colThreeFail = elemOffset == failElemOffset && lineno == failCallLineNo && colno == failCallColNo && access == threadTwoFailAccess;
+
+ checkCallExpected = false;
+ PrintDetailedTraceLine(colOne, colTwo, colThree, colOneLength, colTwoLength, colThreeLength, colTwoFail, colThreeFail);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ private static LiteralExpr ExtractSourceLineArg(Expr e)
+ {
+ var visitor = new GetThenOfIfThenElseVisitor();
+ visitor.VisitExpr(e);
+ return visitor.getResult();
+ }
+
+ private static Expr ExtractOffsetArg(Expr e, string pattern)
+ {
+ var visitor = new GetRHSOfEqualityVisitor(pattern);
+ visitor.VisitExpr(e);
+ return visitor.getResult();
+ }
+
+ private static IdentifierExpr ExtractEnabledArg(Expr e)
+ {
+ var visitor = new GetIfOfIfThenElseVisitor();
+ visitor.VisitExpr(e);
+ return visitor.getResult();
+ }
+
+ private static string ExtractEnabledParameterName(Expr e)
+ {
+ if (e is IdentifierExpr)
+ {
+ return ((IdentifierExpr)e).Name;
+ }
+ else
+ {
+ Debug.Assert(e is NAryExpr);
+ return ExtractEnabledParameterName(((NAryExpr)e).Args[0]);
+ }
+ }
+
+ private static int ExtractOffsetFromExpr(Model model, Expr offsetArg)
+ {
+ if (offsetArg is LiteralExpr)
+ {
+ return ((offsetArg as LiteralExpr).Val as BvConst).Value.ToIntSafe;
+ }
+ else if (offsetArg is IdentifierExpr)
+ {
+ string offsetname = (offsetArg as IdentifierExpr).Name;
+ Model.Func fo = model.TryGetFunc(offsetname);
+ Debug.Assert(fo != null, "ExtractOffsetFromExpr(): could not get value for the following from model: " + offsetname);
+ Debug.Assert(fo.AppCount == 1, "ExtractOffsetFromExpr(): the following function has more than one application: " + offsetname);
+ return (fo.Apps.ElementAt(0).Result as Model.BitVector).AsInt();
+
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ private static void PrintDetailedTraceLine(string colOne, string colTwo, string colThree, int colOneLength, int colTwoLength, int colThreeLength, bool colTwoError, bool colThreeError)
+ {
+ Contract.Requires(colOneLength >= colOne.Length && colTwoLength >= colTwo.Length && colThreeLength >= colThree.Length);
+ Console.Write("{0}|", colOne + Chars(colOneLength - colOne.Length, ' '));
+
+ ConsoleColor col = Console.ForegroundColor;
+ if (colTwoError)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ }
+ Console.Write("{0}", colTwo + Chars(colTwoLength - colTwo.Length, ' '));
+ Console.ForegroundColor = col;
+ Console.Write('|');
+
+ if (colThreeError)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ }
+ Console.WriteLine("{0}", colThree + Chars(colThreeLength - colThree.Length, ' '));
+ Console.ForegroundColor = col;
+
+ }
+
+ private static string GetSourceLocFileName()
+ {
+ return GetFilenamePathPrefix() + GetFileName() + ".loc";
+ }
+
+ private static string GetFileName()
+ {
+ return Path.GetFileNameWithoutExtension(CommandLineOptions.Clo.Files[0]);
+ }
+
+ private static string GetFilenamePathPrefix()
+ {
+ string directoryName = Path.GetDirectoryName(CommandLineOptions.Clo.Files[0]);
+ return ((!String.IsNullOrEmpty(directoryName) && directoryName != ".") ? (directoryName + Path.DirectorySeparatorChar) : "");
+ }
+
+ private static string GetCorrespondingThreadTwoName(string threadOneName)
+ {
+ return threadOneName.Replace("$1", "$2");
+ }
+ static QKeyValue CreateSourceLocQKV(int line, int col, string fname, string dir)
+ {
+ QKeyValue dirkv = new QKeyValue(Token.NoToken, "dir", new List<object>(new object[] { dir }), null);
+ QKeyValue fnamekv = new QKeyValue(Token.NoToken, "fname", new List<object>(new object[] { fname }), dirkv);
+ QKeyValue colkv = new QKeyValue(Token.NoToken, "col", new List<object>(new object[] { new LiteralExpr(Token.NoToken, BigNum.FromInt(col)) }), fnamekv);
+ QKeyValue linekv = new QKeyValue(Token.NoToken, "line", new List<object>(new object[] { new LiteralExpr(Token.NoToken, BigNum.FromInt(line)) }), colkv);
+ return linekv;
+ }
+
+ static QKeyValue GetSourceLocInfo(Counterexample error, string AccessType) {
+ string sourceVarName = null;
+ int sourceLocLineNo = -1;
+
+ foreach (Block b in error.Trace)
+ {
+ foreach (Cmd c in b.Cmds)
+ {
+ if (b.tok.val.Equals("_LOG_" + AccessType) && c.ToString().Contains(AccessType + "_SOURCE_"))
+ {
+ sourceVarName = Regex.Split(c.ToString(), " ")[1];
+ }
+ }
+ }
+ if (sourceVarName != null)
+ {
+ Model.Func f = error.Model.TryGetFunc(sourceVarName);
+ if (f != null)
+ {
+ sourceLocLineNo = f.GetConstant().AsInt();
+ }
+ }
+
+ if (sourceLocLineNo > 0)
+ {
+ // TODO: Make lines in .loc file be indexed from 1 for consistency.
+ string fileLine = FetchCodeLine(GetSourceLocFileName(), sourceLocLineNo + 1);
+ if (fileLine != null)
+ {
+ string[] slocTokens = Regex.Split(fileLine, "#");
+ return CreateSourceLocQKV(
+ System.Convert.ToInt32(slocTokens[0]),
+ System.Convert.ToInt32(slocTokens[1]),
+ slocTokens[2],
+ slocTokens[3]);
+ }
+ }
+ else
+ {
+ Console.WriteLine("sourceLocLineNo is {0}. No sourceloc at that location.\n", sourceLocLineNo);
+ return null;
+ }
+ return null;
+ }
+
+ static bool IsRepeatedKV(QKeyValue attrs, List<QKeyValue> alreadySeen)
+ {
+ return false;
+ /*
+ if (attrs == null)
+ {
+ return false;
+ }
+ string key = null;
+ foreach (QKeyValue qkv in alreadySeen)
+ {
+ QKeyValue kv = qkv.Clone() as QKeyValue;
+ if (kv.Params.Count != attrs.Params.Count)
+ {
+ return false;
+ }
+ for (; kv != null; kv = kv.Next) {
+ key = kv.Key;
+ if (key != "thread") {
+ if (kv.Params.Count == 0)
+ {
+ if (QKeyValue.FindBoolAttribute(attrs, key))
+ {
+ continue;
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+ else if (kv.Params[0] is LiteralExpr)
+ { // int
+ LiteralExpr l = kv.Params[0] as LiteralExpr;
+ int i = l.asBigNum.ToIntSafe;
+ if (QKeyValue.FindIntAttribute(attrs, key, -1) == i)
+ {
+ continue;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (kv.Params[0] is string)
+ { // string
+ string s = kv.Params[0] as string;
+ if (QKeyValue.FindStringAttribute(attrs, key) == s)
+ {
+ continue;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ Debug.Assert(false);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ */
+ }
+
+ private static void ReportFailingAssert(Absy node)
+ {
+ Console.WriteLine("");
+
+ int failLine = -1, failCol = -1;
+ string failFile = null, locinfo = null;
+
+ QKeyValue attrs = GetAttributes(node);
+ Debug.Assert(attrs != null, "ReportFailingAssert(): null attributes.");
+
+ GetLocInfoFromAttrs(attrs, out failLine, out failCol, out failFile);
+
+ Debug.Assert(failLine != -1 && failCol != -1 && failFile != null, "ReportFailingAssert(): could not get source location.",
+ "Sourceloc info not found for {0}:{1}:{2}\n", node.tok.filename, node.tok.line, node.tok.col);
+
+ locinfo = failFile + ":" + failLine + ":" + failCol + ":";
+
+ ErrorWriteLine(locinfo, "this assertion might not hold", ErrorMsgType.Error);
+ ErrorWriteLine(FetchCodeLine(failFile, failLine));
+ }
+
+ private static void ReportInvariantMaintedFailure(Absy node)
+ {
+ Console.WriteLine("");
+
+ int failLine = -1, failCol = -1;
+ string failFile = null, locinfo = null;
+
+ QKeyValue attrs = GetAttributes(node);
+ Debug.Assert(attrs != null, "ReportInvariantMaintedFailure(): null attributes.");
+
+ GetLocInfoFromAttrs(attrs, out failLine, out failCol, out failFile);
+
+ Debug.Assert(failLine != -1 && failCol != -1 && failFile != null, "ReportInvariantMaintedFailure(): could not get source location.",
+ "Sourceloc info not found for {0}:{1}:{2}\n", node.tok.filename, node.tok.line, node.tok.col);
+
+ locinfo = failFile + ":" + failLine + ":" + failCol + ":";
+
+ ErrorWriteLine(locinfo, "loop invariant might not be maintained by the loop", ErrorMsgType.Error);
+ ErrorWriteLine(FetchCodeLine(failFile, failLine));
+ }
+
+ private static void ReportInvariantEntryFailure(Absy node)
+ {
+ Console.WriteLine("");
+
+ int failLine = -1, failCol = -1;
+ string failFile = null, locinfo = null;
+
+ QKeyValue attrs = GetAttributes(node);
+ Debug.Assert(attrs != null, "ReportInvariantEntryFailure(): null attributes.");
+
+ GetLocInfoFromAttrs(attrs, out failLine, out failCol, out failFile);
+
+ Debug.Assert(failLine != -1 && failCol != -1 && failFile != null, "ReportInvariantEntryFailure(): could not get source location.",
+ "Sourceloc info not found for {0}:{1}:{2}\n", node.tok.filename, node.tok.line, node.tok.col);
+
+ locinfo = failFile + ":" + failLine + ":" + failCol + ":";
+
+ ErrorWriteLine(locinfo, "loop invariant might not hold on entry", ErrorMsgType.Error);
+ ErrorWriteLine(FetchCodeLine(failFile, failLine));
+ }
+
+ private static void ReportEnsuresFailure(Absy node)
+ {
+ Console.WriteLine("");
+
+ int failLine = -1, failCol = -1;
+ string failFile = null, locinfo = null;
+
+ QKeyValue attrs = GetAttributes(node);
+ Debug.Assert(attrs != null, "ReportEnsuresFailure(): null attributes.");
+
+ GetLocInfoFromAttrs(attrs, out failLine, out failCol, out failFile);
+
+ Debug.Assert(failLine != -1 && failCol != -1 && failFile != null, "ReportEnsuresFailure(): could not get source location.",
+ "Sourceloc info not found for {0}:{1}:{2}\n", node.tok.filename, node.tok.line, node.tok.col);
+
+ locinfo = failFile + ":" + failLine + ":" + failCol + ":";
+
+ ErrorWriteLine(locinfo, "postcondition might not hold on all return paths", ErrorMsgType.Error);
+ ErrorWriteLine(FetchCodeLine(failFile, failLine));
+ }
+
+ private static void ReportRace(Absy callNode, Absy reqNode, string thread1, string thread2, string group1, string group2, string arrName, int byteOffset, RaceType raceType)
+ {
+ Console.WriteLine("");
+ int failLine1 = -1, failCol1 = -1, failLine2 = -1, failCol2 = -1;
+ string failFile1 = null, locinfo1 = null, failFile2 = null, locinfo2 = null, raceName, access1, access2;
+
+ QKeyValue callAttrs = GetAttributes(callNode);
+ QKeyValue reqAttrs = GetAttributes(reqNode);
+
+ Debug.Assert(callAttrs != null, "ReportRace(): null call attributes.");
+ Debug.Assert(reqAttrs != null, "ReportRace(): null req attributes.");
+
+ GetLocInfoFromAttrs(callAttrs, out failLine1, out failCol1, out failFile1);
+ GetLocInfoFromAttrs(reqAttrs, out failLine2, out failCol2, out failFile2);
+
+ Debug.Assert(failLine1 != -1 && failCol1 != -1 && failFile1 != null, "ReportRace(): could not get source location for thread 1",
+ "Sourceloc info not found for {0}:{1}:{2}\n", callNode.tok.filename, callNode.tok.line, callNode.tok.col);
+ Debug.Assert(failLine2 != -1 && failCol2 != -1 && failFile2 != null, "ReportRace(): could not get source location for thread 2",
+ "Sourceloc info not found for {0}:{1}:{2}\n", reqNode.tok.filename, reqNode.tok.line, reqNode.tok.col);
+
+ switch (raceType)
+ {
+ case RaceType.RW:
+ raceName = "read-write";
+ access1 = "read from";
+ access2 = "wrote to";
+ break;
+ case RaceType.WR:
+ raceName = "write-read";
+ access1 = "wrote to";
+ access2 = "read from";
+ break;
+ case RaceType.WW:
+ raceName = "write-write";
+ access1 = "wrote to";
+ access2 = "wrote to";
+ break;
+ default:
+ raceName = null;
+ access1 = null;
+ access2 = null;
+ Debug.Assert(false, "ReportRace(): Reached default case in switch over raceType.");
+ break;
+ }
+ ErrorWriteLine(failFile1 + ":", "possible " + raceName + " race:\n", ErrorMsgType.Error);
+
+ locinfo1 = failFile1 + ":" + failLine1 + ":" + failCol1 + ":";
+ locinfo2 = failFile2 + ":" + failLine2 + ":" + failCol2 + ":";
+
+ AddPadding(ref locinfo1, ref locinfo2);
+ AddPadding(ref access1, ref access2);
+
+ ErrorWriteLine(locinfo1, "thread " + thread2 + " group " + group2 + " " + access2 + " ((char*)" + arrName + ")[" + byteOffset + "]", ErrorMsgType.NoError);
+ ErrorWriteLine(TrimLeadingSpaces(FetchCodeLine(failFile1, failLine1) + "\n", 2));
+
+
+ ErrorWriteLine(locinfo2, "thread " + thread1 + " group " + group1 + " " + access1 + " ((char*)" + arrName + ")[" + byteOffset + "]", ErrorMsgType.NoError);
+ ErrorWriteLine(TrimLeadingSpaces(FetchCodeLine(failFile2, failLine2) + "\n", 2));
+ }
+
+ private static void ReportBarrierDivergence(Absy node)
+ {
+ Console.WriteLine("");
+
+ int failLine = -1, failCol = -1;
+ string failFile = null, locinfo = null;
+
+ QKeyValue attrs = GetAttributes(node);
+ Debug.Assert(attrs != null, "ReportBarrierDivergendce(): null attributes.");
+
+ GetLocInfoFromAttrs(attrs, out failLine, out failCol, out failFile);
+
+ Debug.Assert(failLine != -1 && failCol != -1 && failFile != null, "ReportBarrierDivergence(): could not get source location.",
+ "Sourceloc info not found for {0}:{1}:{2}\n", node.tok.filename, node.tok.line, node.tok.col);
+
+ locinfo = failFile + ":" + failLine + ":" + failCol + ":";
+
+ ErrorWriteLine(locinfo, "barrier may be reached by non-uniform control flow", ErrorMsgType.Error);
+ ErrorWriteLine(FetchCodeLine(failFile, failLine));
+ }
+
+ private static void ReportRequiresFailure(Absy callNode, Absy reqNode)
+ {
+ Console.WriteLine("");
+
+ int failLine1 = -1, failCol1 = -1, failLine2 = -1, failCol2 = -1;
+ string failFile1 = null, locinfo1 = null, failFile2 = null, locinfo2 = null;
+
+ QKeyValue callAttrs = GetAttributes(callNode);
+ QKeyValue reqAttrs = GetAttributes(reqNode);
+
+ Debug.Assert(callAttrs != null, "ReportRace(): null call attributes.");
+ Debug.Assert(reqAttrs != null, "ReportRace(): null req attributes.");
+
+ GetLocInfoFromAttrs(callAttrs, out failLine1, out failCol1, out failFile1);
+ GetLocInfoFromAttrs(reqAttrs, out failLine2, out failCol2, out failFile2);
+
+ Debug.Assert(failLine1 != -1 && failCol1 != -1 && failFile1 != null, "ReportRequiresFailure(): could not get source location from call",
+ "Sourceloc info not found for {0}:{1}:{2}\n", callNode.tok.filename, callNode.tok.line, callNode.tok.col);
+ Debug.Assert(failLine2 != -1 && failCol2 != -1 && failFile2 != null, "ReportRequiresFailure(): could not get source location from requires",
+ "Sourceloc info not found for {0}:{1}:{2}\n", reqNode.tok.filename, reqNode.tok.line, reqNode.tok.col);
+
+ locinfo1 = failFile1 + ":" + failLine1 + ":" + failCol1 + ":";
+ locinfo2 = failFile2 + ":" + failLine2 + ":" + failCol2 + ":";
+
+ ErrorWriteLine(locinfo1, "a precondition for this call might not hold", ErrorMsgType.Error);
+ ErrorWriteLine(TrimLeadingSpaces(FetchCodeLine(failFile1, failLine1), 2));
+
+
+ ErrorWriteLine(locinfo2, "this is the precondition that might not hold", ErrorMsgType.Note);
+ ErrorWriteLine(TrimLeadingSpaces(FetchCodeLine(failFile2, failLine2), 2));
+ }
+
+ private static string FetchCodeLine(string path, int lineNo)
+ {
+ TextReader tr = new StreamReader(path);
+ string line = null;
+
+ for (int currLineNo = 1; ((line = tr.ReadLine()) != null); currLineNo++)
+ {
+ if (currLineNo == lineNo)
+ {
+ break;
+ }
+ }
+ if (line != null)
+ {
+ return line;
+ }
+ else
+ {
+ Console.WriteLine("FetchCodeLine(): could not get line {0} from {1}\n", lineNo, path);
+ return null;
+ }
+ }
+
+ private static void GetLocInfoFromAttrs(QKeyValue attrs, out int failLine, out int failCol, out string failFile)
+ {
+ failLine = QKeyValue.FindIntAttribute(attrs, "line", -1);
+ failCol = QKeyValue.FindIntAttribute(attrs, "col", -1);
+ failFile = GetFilenamePathPrefix() + QKeyValue.FindStringAttribute(attrs, "fname");
+ }
+
+ private static void GetThreadsAndGroupsFromModel(Model model, out string thread1, out string thread2, out string group1, out string group2, bool withSpaces)
+ {
+ thread1 = GetThreadOne(model, withSpaces);
+ thread2 = GetThreadTwo(model, withSpaces);
+ group1 = GetGroupOne(model, withSpaces);
+ group2 = GetGroupTwo(model, withSpaces);
+ }
+
+ private static string GetGroupTwo(Model model, bool withSpaces)
+ {
+ return "("
+ + GetGidX2(model)
+ + "," + (withSpaces ? " " : "")
+ + GetGidY2(model)
+ + "," + (withSpaces ? " " : "")
+ + GetGidZ2(model)
+ + ")";
+ }
+
+ private static int GetGidZ2(Model model)
+ {
+ return model.TryGetFunc("group_id_z$2").GetConstant().AsInt();
+ }
+
+ private static int GetGidY2(Model model)
+ {
+ return model.TryGetFunc("group_id_y$2").GetConstant().AsInt();
+ }
+
+ private static int GetGidX2(Model model)
+ {
+ return model.TryGetFunc("group_id_x$2").GetConstant().AsInt();
+ }
+
+ private static string GetGroupOne(Model model, bool withSpaces)
+ {
+ return "("
+ + GetGidX1(model)
+ + "," + (withSpaces ? " " : "")
+ + GetGidY1(model)
+ + "," + (withSpaces ? " " : "")
+ + GetGidZ1(model)
+ + ")";
+ }
+
+ private static int GetGidZ1(Model model)
+ {
+ return model.TryGetFunc("group_id_z$1").GetConstant().AsInt();
+ }
+
+ private static int GetGidY1(Model model)
+ {
+ return model.TryGetFunc("group_id_y$1").GetConstant().AsInt();
+ }
+
+ private static int GetGidX1(Model model)
+ {
+ return model.TryGetFunc("group_id_x$1").GetConstant().AsInt();
+ }
+
+ private static string GetThreadTwo(Model model, bool withSpaces)
+ {
+ return "("
+ + GetLidX2(model)
+ + "," + (withSpaces ? " " : "")
+ + GetLidY2(model)
+ + "," + (withSpaces ? " " : "")
+ + GetLidZ2(model)
+ + ")";
+ }
+
+ private static int GetLidZ2(Model model)
+ {
+ return model.TryGetFunc("local_id_z$2").GetConstant().AsInt();
+ }
+
+ private static int GetLidY2(Model model)
+ {
+ return model.TryGetFunc("local_id_y$2").GetConstant().AsInt();
+ }
+
+ private static int GetLidX2(Model model)
+ {
+ return model.TryGetFunc("local_id_x$2").GetConstant().AsInt();
+ }
+
+ private static string GetThreadOne(Model model, bool withSpaces)
+ {
+ return "("
+ + model.TryGetFunc("local_id_x$1").GetConstant().AsInt()
+ + "," + (withSpaces ? " " : "")
+ + model.TryGetFunc("local_id_y$1").GetConstant().AsInt()
+ + "," + (withSpaces ? " " : "")
+ + model.TryGetFunc("local_id_z$1").GetConstant().AsInt()
+ + ")";
+ }
+
+ private static void GetInfoFromVarAndFunc(QKeyValue attrs, Model.Func f, out int byteOffset, out int elemOffset, out int elemWidth, out string arrName)
+ {
+ Debug.Assert(f != null && f.AppCount == 1);
+ elemOffset = f.Apps.FirstOrDefault().Result.AsInt();
+ arrName = ExtractArrName(f.Name);
+ elemWidth = QKeyValue.FindIntAttribute(attrs, "elem_width", -1);
+ Debug.Assert(elemWidth != -1, "GetInfoFromVarAndFunc: Could not find \"elem_width\" attribute.");
+ byteOffset = CalculateByteOffset(elemOffset, elemWidth);
+ }
+
+ private static int CalculateByteOffset(int elemOffset, int elemWidth)
+ {
+ return (elemOffset * elemWidth) / 8;
+ }
+
+ private static string ExtractArrName(string varName)
+ {
+ return Regex.Split(varName, "[$]+")[1];
+ }
+
+ private static Variable ExtractOffsetVar(NAryExpr expr)
+ {
+ foreach (Expr e in expr.Args)
+ {
+ if (e is NAryExpr && e.ToString().Contains("_OFFSET_"))
+ {
+ return ExtractOffsetVar(e as NAryExpr);
+ }
+ else if (e is IdentifierExpr && (e as IdentifierExpr).Name.Contains("_OFFSET_"))
+ {
+ return (e as IdentifierExpr).Decl;
+ }
+ else continue;
+ }
+ Debug.Assert(false, "GPUVerifyBoogieDriver: ExtractOffsetExpr() could not find _OFFSET expr.");
+ return null;
+ }
+
}
}
diff --git a/Source/GPUVerifyBoogieDriver/GPUVerifyBoogieDriver.csproj b/Source/GPUVerifyBoogieDriver/GPUVerifyBoogieDriver.csproj
index 6f616936..06300e1f 100644
--- a/Source/GPUVerifyBoogieDriver/GPUVerifyBoogieDriver.csproj
+++ b/Source/GPUVerifyBoogieDriver/GPUVerifyBoogieDriver.csproj
@@ -43,6 +43,9 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="GetIfOfIfThenElseVisitor.cs" />
+ <Compile Include="GetRHSOfEqualityVisitor.cs" />
+ <Compile Include="GetThenOfIfThenElseVisitor.cs" />
<Compile Include="GPUVerifyBoogieDriver.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
diff --git a/Source/GPUVerifyBoogieDriver/GetIfOfIfThenElseVisitor.cs b/Source/GPUVerifyBoogieDriver/GetIfOfIfThenElseVisitor.cs
new file mode 100644
index 00000000..a7c6be8a
--- /dev/null
+++ b/Source/GPUVerifyBoogieDriver/GetIfOfIfThenElseVisitor.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+
+namespace Microsoft.Boogie
+{
+ class GetIfOfIfThenElseVisitor : StandardVisitor
+ {
+ IdentifierExpr result;
+
+ internal GetIfOfIfThenElseVisitor()
+ {
+ result = null;
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ if (node.Fun is IfThenElse)
+ {
+ if (node.Args[0] is IdentifierExpr)
+ {
+ Debug.Assert(result == null);
+ result = node.Args[0] as IdentifierExpr;
+ }
+ else if (node.Args[0] is NAryExpr)
+ {
+ Debug.Assert(result == null);
+ result = ExtractEnabledArg((NAryExpr)node.Args[0]);
+ }
+ }
+ return base.VisitNAryExpr(node);
+ }
+
+ internal IdentifierExpr getResult()
+ {
+ Debug.Assert(result != null);
+ return result;
+ }
+
+ internal IdentifierExpr ExtractEnabledArg(NAryExpr ne)
+ {
+ if (ne.Args[0] is IdentifierExpr)
+ {
+ return (IdentifierExpr)ne.Args[0];
+ }
+ else if (ne.Args[0] is NAryExpr)
+ {
+ return ExtractEnabledArg((NAryExpr)ne.Args[0]);
+ }
+ else
+ {
+ Debug.Assert(false, "ExtractEnabledArg: not all cases covered");
+ return null;
+ }
+ }
+ }
+}
diff --git a/Source/GPUVerifyBoogieDriver/GetRHSOfEqualityVisitor.cs b/Source/GPUVerifyBoogieDriver/GetRHSOfEqualityVisitor.cs
new file mode 100644
index 00000000..f13c28cf
--- /dev/null
+++ b/Source/GPUVerifyBoogieDriver/GetRHSOfEqualityVisitor.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+
+namespace Microsoft.Boogie
+{
+ class GetRHSOfEqualityVisitor : StandardVisitor
+ {
+
+ string LHSPattern;
+ Expr result;
+
+ internal GetRHSOfEqualityVisitor(string LHSPattern)
+ {
+ this.LHSPattern = LHSPattern;
+ result = null;
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ if (node.Fun is BinaryOperator && ((BinaryOperator)node.Fun).Op == BinaryOperator.Opcode.Eq)
+ {
+ if (node.Args[0] is IdentifierExpr && Regex.IsMatch(((IdentifierExpr)node.Args[0]).Decl.Name, LHSPattern))
+ {
+ Debug.Assert(result == null);
+ result = node.Args[1];
+ }
+ }
+ return base.VisitNAryExpr(node);
+ }
+
+ internal Expr getResult()
+ {
+ Debug.Assert(result != null);
+ return result;
+ }
+
+ }
+}
diff --git a/Source/GPUVerifyBoogieDriver/GetThenOfIfThenElseVisitor.cs b/Source/GPUVerifyBoogieDriver/GetThenOfIfThenElseVisitor.cs
new file mode 100644
index 00000000..dbecda97
--- /dev/null
+++ b/Source/GPUVerifyBoogieDriver/GetThenOfIfThenElseVisitor.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+
+namespace Microsoft.Boogie
+{
+ class GetThenOfIfThenElseVisitor : StandardVisitor
+ {
+ LiteralExpr result;
+
+ internal GetThenOfIfThenElseVisitor()
+ {
+ result = null;
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ if (node.Fun is IfThenElse)
+ {
+ if (node.Args[1] is LiteralExpr)
+ {
+ Debug.Assert(result == null);
+ result = (LiteralExpr)node.Args[1];
+ }
+ }
+ return base.VisitNAryExpr(node);
+ }
+
+ internal LiteralExpr getResult()
+ {
+ Debug.Assert(result != null);
+ return result;
+ }
+ }
+}
diff --git a/Source/Graph/Graph.cs b/Source/Graph/Graph.cs
index 654360f4..947a5882 100644
--- a/Source/Graph/Graph.cs
+++ b/Source/Graph/Graph.cs
@@ -1,948 +1,1378 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
using System;
-using System.Collections.Generic;
-using System.Text; // for StringBuilder
-using System.Diagnostics.Contracts;
-namespace Graphing {
-
- internal static class Util {
- private static string/*!*/ ListToString<T>(IEnumerable<T> xs) {
- Contract.Ensures(Contract.Result<string>() != null);
- StringBuilder sb = new StringBuilder();
- sb.Append("[");
- bool first = true;
- foreach (T/*!*/ x in xs) {
- Contract.Assert(x != null);
- if (!first)
- sb.Append(", ");
- sb.Append(x.ToString());
- first = false;
- }
- sb.Append("]");
- return sb.ToString();
- }
- public static string/*!*/ MapToString<Node>(Dictionary<Node, List<Node>> d) {
- Contract.Ensures(Contract.Result<string>() != null);
- StringBuilder sb = new StringBuilder();
- sb.Append("{");
- bool first = true;
- foreach (KeyValuePair<Node, List<Node>> de in d) {
- if (!first)
- sb.Append(", ");
- Contract.Assert(!object.Equals(de.Key,default(Node)));
- sb.Append(de.Key.ToString());
- sb.Append("~>");
- sb.Append(ListToString(de.Value));
- first = false;
- }
- sb.Append("}");
- return sb.ToString();
- }
- }
+using System.Linq;
+using System.Collections.Generic;
+using System.Text; // for StringBuilder
+using System.Diagnostics.Contracts;
+namespace Microsoft.Boogie.GraphUtil {
+
+ internal static class Util {
+ private static string/*!*/ ListToString<T>(IEnumerable<T> xs) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ StringBuilder sb = new StringBuilder();
+ sb.Append("[");
+ bool first = true;
+ foreach (T/*!*/ x in xs) {
+ Contract.Assert(x != null);
+ if (!first)
+ sb.Append(", ");
+ sb.Append(x.ToString());
+ first = false;
+ }
+ sb.Append("]");
+ return sb.ToString();
+ }
+ public static string/*!*/ MapToString<Node>(Dictionary<Node, List<Node>> d) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ StringBuilder sb = new StringBuilder();
+ sb.Append("{");
+ bool first = true;
+ foreach (KeyValuePair<Node, List<Node>> de in d) {
+ if (!first)
+ sb.Append(", ");
+ Contract.Assert(!object.Equals(de.Key,default(Node)));
+ sb.Append(de.Key.ToString());
+ sb.Append("~>");
+ sb.Append(ListToString(de.Value));
+ first = false;
+ }
+ sb.Append("}");
+ return sb.ToString();
+ }
+ }
+
+ // own struct to represent possibly undefined values, because Mono does
+ // not like arrays with element type T! or T?
+ public struct Maybe<T> {
+ private T Value;
+ public bool IsSet; // initialised with false by the default ctor
+ public T Val {
+ get {
+ Contract.Assume(IsSet);
+ return Value;
+ }
+ set {
+ Value = value;
+ IsSet = true;
+ }
+ }
+ public void UnSet() {
+ IsSet = false;
+ }
+ }
+
+ public class DomRelation<Node> {
+ // doms maps (unique) node numbers to the node numbers of the immediate dominator
+ // to use it on Nodes, one needs the two way mapping between nodes and their numbers.
+ private int[] doms; // 0 is unused: means undefined
+ // here are the two mappings
+ private Maybe<Node>[] postOrderNumberToNode;
+ private Dictionary<Node, int> nodeToPostOrderNumber;
+ private int sourceNum; // (number for) root of the graph
+ private Node source; // root of the graph
+ private Graph<Node> graph;
+ private Dictionary<Node, List<Node>> immediateDominatorMap;
+
+ [NotDelayed]
+ internal DomRelation(Graph<Node> g, Node source) {
+ this.graph = g;
+ // slot 0 not used: nodes are numbered from 1 to n so zero
+ // can represent undefined.
+ this.source = source;
+ //:base();
+ this.NewComputeDominators();
+ }
+ public Dictionary<Node, List<Node>> ImmediateDominatorMap {
+ get {
+ Contract.Assume(this.immediateDominatorMap != null);
+ return this.immediateDominatorMap;
+ }
+ }
+ public bool DominatedBy(Node dominee, Node dominator, List<Node> path = null) {
+ Contract.Assume(this.nodeToPostOrderNumber != null);
+ Contract.Assume(this.doms != null);
+ int domineeNum = this.nodeToPostOrderNumber[dominee];
+ int dominatorNum = this.nodeToPostOrderNumber[dominator];
+ if (domineeNum == dominatorNum)
+ return true;
+ int currentNodeNum = this.doms[domineeNum];
+ while (true) {
+ if (currentNodeNum == dominatorNum)
+ return true;
+ if (currentNodeNum == this.sourceNum)
+ return false;
+ if (path != null)
+ path.Add(postOrderNumberToNode[currentNodeNum].Val);
+ currentNodeNum = this.doms[currentNodeNum];
+ }
+ }
+ private Dictionary<Node, List<Node>> domMap = null;
+ [Pure]
+ public override string ToString() {
+ Contract.Assume(this.doms != null);
+ int[] localDoms = this.doms;
+ Contract.Assume(this.postOrderNumberToNode != null);
+ if (domMap == null) {
+ domMap = new Dictionary<Node, List<Node>>();
+ for (int i = 1; i < localDoms.Length; i++) { // 0 slot is not used
+ int domineeNum = i;
+ int currentNodeNum = domineeNum;
+ List<Node> dominators = new List<Node>();
+ while (currentNodeNum != this.sourceNum) {
+ dominators.Add(this.postOrderNumberToNode[currentNodeNum].Val);
+ currentNodeNum = this.doms[currentNodeNum];
+ }
+ dominators.Add(this.postOrderNumberToNode[this.sourceNum].Val);
+ domMap.Add(this.postOrderNumberToNode[i].Val, dominators);
+ }
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.Append("{");
+ bool first = true;
+ foreach (KeyValuePair<Node, List<Node>> de in domMap) {
+ if (!first)
+ sb.Append(", ");
+ Contract.Assert(!object.Equals(de.Key, default(Node)));
+ sb.Append(de.Key.ToString());
+ sb.Append("~>");
+ sb.Append(ListToString(de.Value));
+ first = false;
+ }
+ sb.Append("}");
+ return sb.ToString();
+ }
+ private void PrintIntArray(int[] xs) {
+ Console.Write("[");
+ for (int i = 0; i < xs.Length; i++) {
+ if (0 < i)
+ Console.Write(", ");
+ Console.Write(xs[i]);
+ }
+ Console.WriteLine("]");
+ }
+ public void PrintList<T>(IEnumerable<T> xs) {
+ Console.Write("[");
+ int i = 0;
+ foreach (T/*!*/ x in xs) {
+ Contract.Assert(x != null);
+ if (0 < i)
+ Console.Write(", ");
+ Console.Write(x.ToString());
+ i++;
+ }
+ Console.WriteLine("]");
+ }
+ public string/*!*/ ListToString<T>(IEnumerable<T> xs) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ StringBuilder sb = new StringBuilder();
+ sb.Append("[");
+ bool first = true;
+ foreach (T/*!*/ x in xs) {
+ Contract.Assert(x != null);
+ if (!first)
+ sb.Append(", ");
+ sb.Append(x.ToString());
+ first = false;
+ }
+ sb.Append("]");
+ return sb.ToString();
+ }
+
+ // Keith D. Cooper, Timothy J. Harvey, Ken Kennedy, "A Simple, Fast Dominance Algorithm ", Software Practice and Experience, 2001.
+ // http://citeseer.ist.psu.edu/cooper01simple.html
+ private void NewComputeDominators() {
+ int n = this.graph.Nodes.Count;
+ this.postOrderNumberToNode = new Maybe<Node>[n + 1];
+ this.nodeToPostOrderNumber = new Dictionary<Node, int>();
+ //HashSet<Node> visited = new HashSet<Node>();
+ //int currentNumber = 1;
+ Contract.Assume(this.source != null);
+ //this.PostOrderVisit(this.source, visited, ref currentNumber);
+ this.PostOrderVisitIterative(this.source);
+ this.sourceNum = this.nodeToPostOrderNumber[source];
+ // for (int i = 1; i <= n; i++){ Console.WriteLine(postOrderNumberToNode[i]); }
+ this.doms = new int[n + 1]; // 0 is unused: means undefined
+ Node start_node = this.source;
+ this.doms[this.nodeToPostOrderNumber[start_node]] = this.nodeToPostOrderNumber[start_node];
+ bool changed = true;
+ // PrintIntArray(doms);
+ while (changed) {
+ changed = false;
+ // for all nodes, b, in reverse postorder (except start_node)
+ for (int nodeNum = n - 1; 1 <= nodeNum; nodeNum--) {
+ Node b = this.postOrderNumberToNode[nodeNum].Val;
+ IEnumerable<Node> predecessors = this.graph.Predecessors(b);
+ // find a predecessor (i.e., a higher number) for which
+ // the doms array has been set
+ int new_idom = 0;
+ int first_processed_predecessor = 0;
+ #region new_idom <- number of first (processed) predecessor of b (pick one)
+ foreach (Node p in predecessors) {
+ if (this.doms[this.nodeToPostOrderNumber[p]] != 0) {
+ int x = this.nodeToPostOrderNumber[p];
+ new_idom = x;
+ first_processed_predecessor = x;
+ break;
+ }
+ }
+ #endregion
+ #region for all other predecessors, p, of b
+ foreach (Node p in predecessors) {
+ if (this.nodeToPostOrderNumber[p] == first_processed_predecessor) {
+ continue;
+ }
+ if (this.doms[this.nodeToPostOrderNumber[p]] != 0)
+ new_idom = intersect(this.nodeToPostOrderNumber[p], new_idom, this.doms);
+ }
+ #endregion
+ if (this.doms[this.nodeToPostOrderNumber[b]] != new_idom) {
+ this.doms[this.nodeToPostOrderNumber[b]] = new_idom;
+ changed = true;
+ }
+ }
+ }
+ #region Populate the Immediate Dominator Map
+ int sourceNum = this.nodeToPostOrderNumber[this.source];
+ immediateDominatorMap = new Dictionary<Node, List<Node>>();
+ for (int i = 1; i <= n; i++) {
+ Node node = this.postOrderNumberToNode[i].Val;
+ Node idomNode = this.postOrderNumberToNode[this.doms[i]].Val;
+ if (i == sourceNum && this.doms[i] == sourceNum) {
+ continue;
+ }
+ if (immediateDominatorMap.ContainsKey(idomNode)) {
+ immediateDominatorMap[idomNode].Add(node);
+ } else {
+ List<Node> l = new List<Node>();
+ l.Add(node);
+ immediateDominatorMap.Add(idomNode, l);
+ }
+ }
+ #endregion
+ }
+ private int intersect(int b1, int b2, int[] doms) {
+ int finger1 = b1;
+ int finger2 = b2;
+ while (finger1 != finger2) {
+ while (finger1 < finger2) {
+ finger1 = doms[finger1];
+ }
+ while (finger2 < finger1) {
+ finger2 = doms[finger2];
+ }
+ }
+ return finger1;
+ }
+ private void PostOrderVisit(Node/*!*/ n, HashSet<Node> visited, ref int currentNumber) {
+ Contract.Requires(n != null);
+ if (visited.Contains(n))
+ return;
+ visited.Add(n);
+ foreach (Node/*!*/ child in this.graph.Successors(n)) {
+ Contract.Assert(child != null);
+ PostOrderVisit(child, visited, ref currentNumber);
+ }
+ Contract.Assume(this.postOrderNumberToNode != null);
+ Contract.Assume(this.nodeToPostOrderNumber != null);
+ this.postOrderNumberToNode[currentNumber].Val = n;
+ this.nodeToPostOrderNumber[n] = currentNumber;
+ currentNumber++;
+ return;
+ }
+ // Iterative version: mimics the above recursive procedure
+ private void PostOrderVisitIterative(Node n)
+ {
+ Contract.Requires(n != null);
+ var visited = new HashSet<Node>();
+ var grey = new HashSet<Node>();
+ var stack = new Stack<Node>();
+
+ int currentNumber = 1;
+
+ stack.Push(n);
+ visited.Add(n);
+
+ while (stack.Count != 0)
+ {
+ var curr = stack.Pop();
+
+ if (grey.Contains(curr))
+ {
+ Contract.Assume(this.postOrderNumberToNode != null);
+ Contract.Assume(this.nodeToPostOrderNumber != null);
+ this.postOrderNumberToNode[currentNumber].Val = curr;
+ this.nodeToPostOrderNumber[curr] = currentNumber;
+ currentNumber++;
+ }
+ else
+ {
+ grey.Add(curr);
+ stack.Push(curr);
+ foreach (Node/*!*/ child in this.graph.Successors(curr))
+ {
+ Contract.Assert(child != null);
+ if (!visited.Contains(child))
+ {
+ visited.Add(child);
+ stack.Push(child);
+ }
+ }
+ }
+
+ }
+
+
+ }
+
+ public Node LeastCommonAncestor(Node n1, Node n2)
+ {
+ var nums = new HashSet<int>();
+ int num1 = nodeToPostOrderNumber[n1], num2 = nodeToPostOrderNumber[n2];
+
+ while (true)
+ {
+ if (!nums.Add(num1))
+ return postOrderNumberToNode[num1].Val;
+ if (!nums.Add(num2))
+ return postOrderNumberToNode[num2].Val;
+ num1 = doms[num1]; num2 = doms[num2];
+ }
+ }
+ }
+
+ public class Graph<Node> {
+ private HashSet<Tuple<Node/*!*/, Node/*!*/>> es;
+ private HashSet<Node> ns;
+ private Node source;
+ private bool reducible;
+ private HashSet<Node> headers;
+ private Dictionary<Node, HashSet<Node>> backEdgeNodes;
+ private Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops;
+ private HashSet<Node> splitCandidates;
+
+ private DomRelation<Node> dominatorMap = null;
+ private Dictionary<Node, HashSet<Node>> predCache = new Dictionary<Node, HashSet<Node>>();
+ private Dictionary<Node, HashSet<Node>> succCache = new Dictionary<Node, HashSet<Node>>();
+ private bool predComputed;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(es == null || Contract.ForAll(es, p => p.Item1 != null && p.Item2 != null));
+ Contract.Invariant(naturalLoops == null || Contract.ForAll(naturalLoops.Keys, p => p.Item2 != null && p.Item1 != null));
+ }
+
+ private class PreHeader {
+ Node/*!*/ myHeader;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(myHeader != null);
+ }
+
+ internal PreHeader(Node/*!*/ h) {
+ Contract.Requires(h != null);
+ myHeader = h;
+ }
+
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return "#" + myHeader.ToString();
+ }
+ }
+
+ public Graph(HashSet<Tuple<Node/*!*/, Node/*!*/>> edges) {
+
+ Contract.Requires(cce.NonNullElements(edges) && Contract.ForAll(edges, p => p.Item1 != null && p.Item2 != null));
+ es = edges;
+
+ // original A#
+ //ns = Set<Node>{ x : <x,y> in es } + Set<Node>{ y : <x,y> in es };
+
+ // closest Spec#
+ //ns = new Set<Node>{ Tuple<Node,Node> p in edges; p.Item1 } + new Set<Node>{ Tuple<Node,Node> p in edges; p.Item2 };
+
+ //
+ HashSet<Node> temp = new HashSet<Node>();
+ foreach (Tuple<Node/*!*/, Node/*!*/> p in edges) {
+ Contract.Assert(p.Item1 != null);
+ temp.Add(p.Item1);
+ Contract.Assert(p.Item2 != null);
+ temp.Add(p.Item2);
+ }
+ ns = temp;
+ }
+ public Graph() {
+ es = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
+ ns = new HashSet<Node>();
+ }
+
+ // BUGBUG: Set<T>.ToString() should return a non-null string
+ [Pure]
+ public override string/*!*/ ToString() {
+ return "" + es.ToString();
+ }
+
+ public void AddSource(Node/*!*/ x) {
+ Contract.Requires(x != null);
+ // BUGBUG: This generates bad code in the compiler
+ //ns += new Set<Node>{x};
+ ns.Add(x);
+ source = x;
+ }
+
+ public void AddEdge(Node/*!*/ source, Node/*!*/ dest) {
+ Contract.Requires(source != null);
+ Contract.Requires(dest != null);
+ //es += Set<Edge>{<source,dest>};
+ //ns += Set<Node>{source, dest};
+ es.Add(new Tuple<Node/*!*/, Node/*!*/>(source, dest));
+ ns.Add(source);
+ ns.Add(dest);
+ predComputed = false;
+ }
+
+ public HashSet<Node> Nodes {
+ get {
+ return ns;
+ }
+ }
+ public IEnumerable<Tuple<Node/*!*/, Node/*!*/>> Edges {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<Tuple<Node, Node>>>())
+ && Contract.ForAll(Contract.Result<IEnumerable<Tuple<Node, Node>>>(), n =>
+ n.Item1 != null && n.Item2 != null));
+ return es;
+ }
+ }
+
+ public bool Edge(Node/*!*/ x, Node/*!*/ y) {
+ Contract.Requires(x != null);
+ Contract.Requires(y != null);
+ // original A#
+ // return <x,y> in es;
+ return es.Contains(new Tuple<Node/*!*/, Node/*!*/>(x, y));
+ }
+
+ private void ComputePredSuccCaches() {
+ if (predComputed)
+ return;
+ predComputed = true;
+ predCache = new Dictionary<Node, HashSet<Node>>();
+ succCache = new Dictionary<Node, HashSet<Node>>();
+
+ foreach (Node n in Nodes) {
+ predCache[n] = new HashSet<Node>();
+ succCache[n] = new HashSet<Node>();
+ }
+
+ foreach (Tuple<Node/*!*/, Node/*!*/> p in Edges) {
+ Contract.Assert(p.Item1 != null);
+ Contract.Assert(p.Item2 != null);
+ HashSet<Node> tmp;
+
+ tmp = predCache[p.Item2];
+ tmp.Add(p.Item1);
+ predCache[p.Item2] = tmp;
+
+ tmp = succCache[p.Item1];
+ tmp.Add(p.Item2);
+ succCache[p.Item1] = tmp;
+ }
+ }
+
+ public IEnumerable<Node> Predecessors(Node n) {
+ // original A#
+ //Set<Node> result = Set{ x : x in Nodes, Edge(x,n) };
+
+ ComputePredSuccCaches();
+ return predCache[n];
+ }
+
+ public IEnumerable<Node> Successors(Node n) {
+ ComputePredSuccCaches();
+ return succCache[n];
+ }
+
+ public List<Node> SuccessorsAsList(Node n) {
+ ComputePredSuccCaches();
+ List<Node> ret = new List<Node>();
+ foreach (Node s in succCache[n])
+ ret.Add(s);
+ return ret;
+ }
+
+ public DomRelation<Node> /*Map<Node,Set<Node>>*/ DominatorMap {
+ get {
+ Contract.Assert(source != null);
+ if (this.dominatorMap == null) {
+ this.dominatorMap = new DomRelation<Node>(this, this.source);
+ }
+ return this.dominatorMap;
+ }
+ }
+
+ public Dictionary<Node, List<Node>> ImmediateDominatorMap {
+ get {
+ Contract.Assert(source != null);
+ if (this.dominatorMap == null) {
+ this.dominatorMap = new DomRelation<Node>(this, this.source);
+ }
+ return this.dominatorMap.ImmediateDominatorMap;
+ }
+ }
+ public List<Node> ImmediatelyDominatedBy(Node/*!*/ n) {
+ Contract.Requires(n != null);
+ List<Node> dominees;
+ this.ImmediateDominatorMap.TryGetValue(n, out dominees);
+ return dominees == null ? new List<Node>() : dominees;
+ }
+
+ public IEnumerable<Node/*?*/> TopologicalSort() {
+ bool acyclic;
+ List<Node> sortedList;
+ this.TarjanTopSort(out acyclic, out sortedList);
+ return acyclic ? sortedList : new List<Node>();
+ }
+ // From Tarjan 1972
+ public void TarjanTopSort(out bool acyclic, out List<Node> sortedNodes) {
+ int n = this.Nodes.Count;
+ if (n == 0) {
+ acyclic = true;
+ sortedNodes = new List<Node>();
+ return;
+ }
+ int[] incomingEdges = new int[n];
+ // need an arbitrary numbering for the nodes to use as indices into
+ // the arrays used within this algorithm
+ Dictionary<Node, int> nodeToNumber = new Dictionary<Node, int>(n);
+ Maybe<Node>[] numberToNode = new Maybe<Node>[n];
+ int counter = 0;
+ foreach (Node node in this.Nodes) {
+ numberToNode[counter].Val = node;
+ nodeToNumber[node] = counter;
+ counter++;
+ }
+ foreach (Tuple<Node/*!*/, Node/*!*/> e in this.Edges) {
+ Contract.Assert(e.Item1 != null);
+ Contract.Assert(e.Item2 != null);
+ Node/*!*/ target = e.Item2;
+ incomingEdges[nodeToNumber[target]]++;
+ }
+ List<Node> sorted = new List<Node>();
+ int sortedIndex = 0;
+ while (sortedIndex < n) {
+ // find a root (i.e., its index)
+ int rootIndex = -1;
+ for (int i = 0; i < n; i++) {
+ if (incomingEdges[i] == 0) {
+ rootIndex = i;
+ break;
+ }
+ }
+ if (rootIndex == -1) {
+ acyclic = false;
+ sortedNodes = new List<Node>();
+ return;
+ }
+ // mark root so it won't be used again
+ incomingEdges[rootIndex] = -1;
+ Node root = numberToNode[rootIndex].Val;
+ sorted.Add(root);
+ ++sortedIndex;
+ foreach (Node s in this.Successors(root)) {
+ incomingEdges[nodeToNumber[s]]--;
+ }
+ }
+ acyclic = true;
+ sortedNodes = sorted;
+ return;
+ }
+ private IEnumerable<Node> OldTopologicalSort() {
+ Tuple<bool, List<Node>> result = this.TopSort();
+ return result.Item1 ? result.Item2 : (IEnumerable<Node>)new List<Node>();
+ }
+ // From AsmL distribution example
+ private Tuple<bool, List<Node>> TopSort()
+ {
+ List<Node> S = new List<Node>();
+ HashSet<Node> V = this.Nodes;
+ HashSet<Node> X = new HashSet<Node>();
+ foreach (Node/*!*/ n in V) {
+ Contract.Assert(n != null);
+ X.Add(n);
+ }
+ bool change = true;
+ while (change)
+ // invariant: X = V - S
+ {
+ change = false;
+ if (X.Count > 0) {
+ foreach (Node/*!*/ n in X) {
+ Contract.Assert(n != null);
+ // see if n has any incoming edges from any other node in X
+ bool inDegreeZero = true;
+ foreach (Node/*!*/ u in X) {
+ Contract.Assert(u != null);
+ if (this.Edge(u, n)) {
+ inDegreeZero = false;
+ break; // no point looking further
+ }
+ }
+ if (inDegreeZero) {
+ S.Add(n);
+ X.Remove(n);
+ change = true;
+ break; // might as well go back and start looking through X from the beginning
+ }
+ }
+ // Then we made it all the way through X without finding a source node
+ if (!change) {
+ return new Tuple<bool, List<Node>>(false, new List<Node>());
+ }
+ }
+ }
+ return new Tuple<bool, List<Node>>(true, S);
+ }
+
+ public static bool Acyclic(Graph<Node> g, Node source) {
+ bool acyclic;
+ List<Node> sortedList;
+ g.TarjanTopSort(out acyclic, out sortedList);
+ return acyclic;
+ }
+
+ // [Dragon, Fig. 10.15, p. 604. Algorithm for constructing the natural loop.]
+ static HashSet<Node> NaturalLoop(Graph<Node> g, Tuple<Node/*!*/, Node/*!*/> backEdge)
+ {
+ Contract.Requires(backEdge.Item1 != null && backEdge.Item2 != null);
+ Node/*!*/ n = backEdge.Item1;
+ Node/*!*/ d = backEdge.Item2;
+ Stack<Node> stack = new Stack<Node>();
+ HashSet<Node> loop = new HashSet<Node>();
+ loop.Add(d);
+ if (!n.Equals(d)) // then n is not in loop
+ {
+ loop.Add(n);
+ stack.Push(n); // push n onto stack
+ }
+ while (stack.Count > 0) // not empty
+ {
+ Node m = stack.Peek();
+ stack.Pop(); // pop stack
+ foreach (Node/*!*/ p in g.Predecessors(m)) {
+ Contract.Assert(p != null);
+ if (!(loop.Contains(p))) {
+ loop.Add(p);
+ stack.Push(p); // push p onto stack
+ }
+ }
+ }
+ return loop;
+ }
+
+ internal struct ReducibleResult {
+ internal bool reducible;
+ internal HashSet<Node> headers;
+ internal Dictionary<Node, HashSet<Node>> backEdgeNodes;
+ internal Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops;
+ internal HashSet<Node> splitCandidates;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Contract.ForAll(naturalLoops.Keys, p => p.Item1 != null && p.Item2 != null));
+ }
+
+ internal ReducibleResult(bool b, HashSet<Node> headers, Dictionary<Node, HashSet<Node>> backEdgeNodes, Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops, HashSet<Node> splitCandidates)
+ {
+ Contract.Requires(naturalLoops == null || Contract.ForAll(naturalLoops.Keys, Key => Key.Item1 != null && Key.Item2 != null));
+ this.reducible = b;
+ this.headers = headers;
+ this.backEdgeNodes = backEdgeNodes;
+ this.naturalLoops = naturalLoops;
+ this.splitCandidates = splitCandidates;
+ }
+
+ }
+
+ // [Dragon, p. 606]
+ static ReducibleResult ComputeReducible(Graph<Node> g, Node source) {
+ // first, compute the dom relation
+ DomRelation<Node> /*Map<Node,Set<Node>>*/ D = g.DominatorMap;
+ return ComputeReducible(g, source, D);
+ }
+
+ static HashSet<Node> FindCycle(Graph<Node> g, Node source) {
+ Stack<Tuple<Node, List<Node>>> stack = new Stack<Tuple<Node, List<Node>>>();
+ HashSet<Node> stackAsSet = new HashSet<Node>();
+ HashSet<Node> visited = new HashSet<Node>();
+ stack.Push(new Tuple<Node, List<Node>>(source, g.SuccessorsAsList(source)));
+ stackAsSet.Add(source);
+ while (stack.Count > 0) {
+ Tuple<Node, List<Node>> tuple = stack.Peek();
+ List<Node> children = tuple.Item2;
+ if (children.Count == 0) {
+ stack.Pop();
+ stackAsSet.Remove(tuple.Item1);
+ continue;
+ }
+ Node n = children[0];
+ children.RemoveAt(0);
+ if (stackAsSet.Contains(n)) {
+ HashSet<Node> ret = new HashSet<Node>();
+ ret.Add(n);
+ while (true) {
+ Node x = stack.Pop().Item1;
+ if (x.Equals(n))
+ return ret;
+ }
+ }
+ if (visited.Contains(n))
+ continue;
+ stack.Push(new Tuple<Node, List<Node>>(n, g.SuccessorsAsList(n)));
+ visited.Add(n);
+ stackAsSet.Add(n);
+ System.Diagnostics.Debug.Assert(stack.Count == stackAsSet.Count);
+ }
+ return new HashSet<Node>();
+ }
+
+ // [Dragon, p. 606]
+ static ReducibleResult ComputeReducible(Graph<Node> g,
+ Node source,
+ DomRelation<Node>/*!*/ DomRelation) {
+ Contract.Requires(DomRelation != null);
+
+ //Console.WriteLine("[" + DateTime.Now +"]: begin ComputeReducible");
+ IEnumerable<Tuple<Node/*!*/, Node/*!*/>> edges = g.Edges;
+ Contract.Assert(Contract.ForAll(edges, n => n.Item1 != null && n.Item2 != null));
+ HashSet<Tuple<Node/*!*/, Node/*!*/>> backEdges = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
+ HashSet<Tuple<Node/*!*/, Node/*!*/>> nonBackEdges = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
+ foreach (Tuple<Node/*!*/, Node/*!*/> e in edges) {
+ Contract.Assert(e.Item1 != null);
+ Contract.Assert(e.Item2 != null);
+ Node x = e.Item1;
+ Node y = e.Item2; // so there is an edge from x to y
+ if (DomRelation.DominatedBy(x, y)) { // y dom x: which means y dominates x
+ backEdges.Add(e);
+ } else {
+ nonBackEdges.Add(e);
+ }
+ }
+ Graph<Node> withoutBackEdges = new Graph<Node>(nonBackEdges);
+ if (!Acyclic(withoutBackEdges, source)) {
+ return new ReducibleResult(false,
+ new HashSet<Node>(),
+ new Dictionary<Node, HashSet<Node>>(),
+ new Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>>(),
+ FindCycle(withoutBackEdges, source));
+ } else {
+ // original A#:
+ //Set<Node> headers = Set{ d : <n,d> in backEdges };
+ HashSet<Node> headers = new HashSet<Node>();
+ foreach (Tuple<Node/*!*/, Node/*!*/> e in backEdges) {
+
+ Contract.Assert(e.Item1 != null);
+ Contract.Assert(e.Item2 != null);
+ headers.Add(e.Item2);
+ }
+ // original A#:
+ //Map<Node,Set<Node>> backEdgeNodes = Map{ h -> bs : h in headers, bs = Set<Node>{ b : <b,x> in backEdges, x == h } };
+ Dictionary<Node, HashSet<Node>> backEdgeNodes = new Dictionary<Node, HashSet<Node>>();
+ foreach (Node/*!*/ h in headers) {
+ Contract.Assert(h != null);
+ HashSet<Node> bs = new HashSet<Node>();
+ foreach (Tuple<Node, Node> backedge in backEdges) {
+ Contract.Assert(backedge.Item1 != null);
+ Contract.Assert(backedge.Item2 != null);
+ if (backedge.Item2.Equals(h)) {
+ bs.Add(backedge.Item1);
+ }
+ }
+ backEdgeNodes.Add(h, bs);
+ }
+
+ // original A#:
+ //Map<Tuple<Node,Node>,Set<Node>> naturalLoops = Map{ e -> NaturalLoop(g,e) : e in backEdges };
+ Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops = new Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>>();
+ foreach (Tuple<Node/*!*/, Node/*!*/> e in backEdges) {
+ Contract.Assert(e.Item1 != null && e.Item2 != null);
+ naturalLoops.Add(e, NaturalLoop(g, e));
+ }
+
+ //Console.WriteLine("[" + DateTime.Now +"]: end ComputeReducible");
+ return new ReducibleResult(true, headers, backEdgeNodes, naturalLoops, new HashSet<Node>());
+ }
+ }
+
+ public bool Reducible {
+ get {
+ return reducible;
+ }
+ }
+ public IEnumerable<Node> Headers {
+ get {
+ return headers;
+ }
+ }
+ public IEnumerable<Node> BackEdgeNodes(Node/*!*/ h) {
+ Contract.Requires(h != null);
+ // original A#:
+ //return h in backEdgeNodes ? backEdgeNodes[h] : null;
+ return (backEdgeNodes.ContainsKey(h) ? backEdgeNodes[h] : (IEnumerable<Node>)new List<Node>());
+ }
+ public IEnumerable<Node> NaturalLoops(Node/*!*/ header, Node/*!*/ backEdgeNode) {
+ Contract.Requires(header != null);
+ Contract.Requires(backEdgeNode != null);
+ Tuple<Node/*!*/, Node/*!*/> e = new Tuple<Node/*!*/, Node/*!*/>(backEdgeNode, header);
+ return naturalLoops.ContainsKey(e) ? naturalLoops[e] : (IEnumerable<Node>)new List<Node>();
+ }
+ public HashSet<Node> SplitCandidates {
+ get {
+ return splitCandidates;
+ }
+ }
+ public void ComputeLoops() {
+ ReducibleResult r = ComputeReducible(this, this.source);
+ this.reducible = r.reducible;
+ this.headers = r.headers;
+ this.backEdgeNodes = r.backEdgeNodes;
+ this.naturalLoops = r.naturalLoops;
+ this.splitCandidates = r.splitCandidates;
+ return;
+ }
+
+ public IEnumerable<Node> SortHeadersByDominance()
+ {
+ Graph<Node> dag = new Graph<Node>();
+ foreach (Node b in headers)
+ {
+ dag.AddSource(b);
+ foreach (Node c in headers)
+ {
+ if (b.Equals(c)) continue;
+ if (DominatorMap.DominatedBy(b, c))
+ {
+ System.Diagnostics.Debug.Assert(!DominatorMap.DominatedBy(c, b));
+ dag.AddEdge(b, c);
+ }
+ }
+ }
+ return dag.TopologicalSort();
+ }
+
+ public string ToDot(Func<Node, string> NodeLabel = null, Func<Node, string> NodeStyle = null) {
+ NodeLabel = NodeLabel ?? (n => n.ToString());
+ NodeStyle = NodeStyle ?? (n => "[shape=box]");
+ var s = new StringBuilder();
+ s.AppendLine("digraph G {");
+ foreach (var n in Nodes)
+ s.AppendLine(" \"" + NodeLabel(n) + "\" " + NodeStyle(n) + ";");
+ foreach (var e in Edges)
+ s.AppendLine(" \"" + NodeLabel(e.Item1) + "\" -> \"" + NodeLabel(e.Item2) + "\";");
+ s.AppendLine("}");
+ return s.ToString();
+ }
+ } // end: class Graph
- // own struct to represent possibly undefined values, because Mono does
- // not like arrays with element type T! or T?
- public struct Maybe<T> {
- private T Value;
- public bool IsSet; // initialised with false by the default ctor
- public T Val {
- get {
- Contract.Assume(IsSet);
- return Value;
- }
- set {
- Value = value;
- IsSet = true;
- }
- }
- public void UnSet() {
- IsSet = false;
- }
- }
+ public static class GraphAlgorithms
+ {
- public class DomRelation<Node> {
- // doms maps (unique) node numbers to the node numbers of the immediate dominator
- // to use it on Nodes, one needs the two way mapping between nodes and their numbers.
- private int[] doms; // 0 is unused: means undefined
- // here are the two mappings
- private Maybe<Node>[] postOrderNumberToNode;
- private Dictionary<Node, int> nodeToPostOrderNumber;
- private int sourceNum; // (number for) root of the graph
- private Node source; // root of the graph
- private Graph<Node> graph;
- private Dictionary<Node, List<Node>> immediateDominatorMap;
-
- [NotDelayed]
- internal DomRelation(Graph<Node> g, Node source) {
- this.graph = g;
- // slot 0 not used: nodes are numbered from 1 to n so zero
- // can represent undefined.
- this.source = source;
- //:base();
- this.NewComputeDominators();
- }
- public Dictionary<Node, List<Node>> ImmediateDominatorMap {
- get {
- Contract.Assume(this.immediateDominatorMap != null);
- return this.immediateDominatorMap;
- }
- }
- public bool DominatedBy(Node dominee, Node dominator) {
- Contract.Assume(this.nodeToPostOrderNumber != null);
- Contract.Assume(this.doms != null);
- int domineeNum = this.nodeToPostOrderNumber[dominee];
- int dominatorNum = this.nodeToPostOrderNumber[dominator];
- if (domineeNum == dominatorNum)
- return true;
- int currentNodeNum = this.doms[domineeNum];
- while (true) {
- if (currentNodeNum == dominatorNum)
- return true;
- if (currentNodeNum == this.sourceNum)
- return false;
- currentNodeNum = this.doms[currentNodeNum];
- }
- }
- private Dictionary<Node, List<Node>> domMap = null;
- [Pure]
- public override string ToString() {
- Contract.Assume(this.doms != null);
- int[] localDoms = this.doms;
- Contract.Assume(this.postOrderNumberToNode != null);
- if (domMap == null) {
- domMap = new Dictionary<Node, List<Node>>();
- for (int i = 1; i < localDoms.Length; i++) { // 0 slot is not used
- int domineeNum = i;
- int currentNodeNum = domineeNum;
- List<Node> dominators = new List<Node>();
- while (currentNodeNum != this.sourceNum) {
- dominators.Add(this.postOrderNumberToNode[currentNodeNum].Val);
- currentNodeNum = this.doms[currentNodeNum];
+ public static Graph<Node> Dual<Node>(this Graph<Node> g, Node dummySource)
+ {
+ var exits = g.Nodes.Where(n => g.Successors(n).Count() == 0).ToList();
+ if (exits.Count == 0)
+ return null;
+ var dual = new Graph<Node>(new HashSet<Tuple<Node, Node>>(g.Edges.Select(e => new Tuple<Node, Node>(e.Item2, e.Item1))));
+ if (exits.Count == 1)
+ dual.AddSource(exits[0]);
+ else
+ {
+ dual.AddSource(dummySource);
+ foreach (var exit in exits)
+ dual.AddEdge(dummySource, exit);
}
- dominators.Add(this.postOrderNumberToNode[this.sourceNum].Val);
- domMap.Add(this.postOrderNumberToNode[i].Val, dominators);
- }
- }
- StringBuilder sb = new StringBuilder();
- sb.Append("{");
- bool first = true;
- foreach (KeyValuePair<Node, List<Node>> de in domMap) {
- if (!first)
- sb.Append(", ");
- Contract.Assert(!object.Equals(de.Key, default(Node)));
- sb.Append(de.Key.ToString());
- sb.Append("~>");
- sb.Append(ListToString(de.Value));
- first = false;
- }
- sb.Append("}");
- return sb.ToString();
- }
- private void PrintIntArray(int[] xs) {
- Console.Write("[");
- for (int i = 0; i < xs.Length; i++) {
- if (0 < i)
- Console.Write(", ");
- Console.Write(xs[i]);
- }
- Console.WriteLine("]");
- }
- public void PrintList<T>(IEnumerable<T> xs) {
- Console.Write("[");
- int i = 0;
- foreach (T/*!*/ x in xs) {
- Contract.Assert(x != null);
- if (0 < i)
- Console.Write(", ");
- Console.Write(x.ToString());
- i++;
- }
- Console.WriteLine("]");
- }
- public string/*!*/ ListToString<T>(IEnumerable<T> xs) {
- Contract.Ensures(Contract.Result<string>() != null);
- StringBuilder sb = new StringBuilder();
- sb.Append("[");
- bool first = true;
- foreach (T/*!*/ x in xs) {
- Contract.Assert(x != null);
- if (!first)
- sb.Append(", ");
- sb.Append(x.ToString());
- first = false;
+ return dual;
}
- sb.Append("]");
- return sb.ToString();
- }
-
- // Keith D. Cooper, Timothy J. Harvey, Ken Kennedy, "A Simple, Fast Dominance Algorithm ", Software Practice and Experience, 2001.
- // http://citeseer.ist.psu.edu/cooper01simple.html
- private void NewComputeDominators() {
- int n = this.graph.Nodes.Count;
- this.postOrderNumberToNode = new Maybe<Node>[n + 1];
- this.nodeToPostOrderNumber = new Dictionary<Node, int>();
- //HashSet<Node> visited = new HashSet<Node>();
- //int currentNumber = 1;
- Contract.Assume(this.source != null);
- //this.PostOrderVisit(this.source, visited, ref currentNumber);
- this.PostOrderVisitIterative(this.source);
- this.sourceNum = this.nodeToPostOrderNumber[source];
- // for (int i = 1; i <= n; i++){ Console.WriteLine(postOrderNumberToNode[i]); }
- this.doms = new int[n + 1]; // 0 is unused: means undefined
- Node start_node = this.source;
- this.doms[this.nodeToPostOrderNumber[start_node]] = this.nodeToPostOrderNumber[start_node];
- bool changed = true;
- // PrintIntArray(doms);
- while (changed) {
- changed = false;
- // for all nodes, b, in reverse postorder (except start_node)
- for (int nodeNum = n - 1; 1 <= nodeNum; nodeNum--) {
- Node b = this.postOrderNumberToNode[nodeNum].Val;
- IEnumerable<Node> predecessors = this.graph.Predecessors(b);
- // find a predecessor (i.e., a higher number) for which
- // the doms array has been set
- int new_idom = 0;
- int first_processed_predecessor = 0;
- #region new_idom <- number of first (processed) predecessor of b (pick one)
- foreach (Node p in predecessors) {
- if (this.doms[this.nodeToPostOrderNumber[p]] != 0) {
- int x = this.nodeToPostOrderNumber[p];
- new_idom = x;
- first_processed_predecessor = x;
- break;
- }
+
+ public static List<Tuple<Node, bool>> LoopyTopSort<Node>(this Graph<Node> g)
+ {
+ Contract.Assert(g.Reducible);
+
+ int n = g.Nodes.Count;
+ var nodeToNumber = new Dictionary<Node, int>(n);
+ var numberToNode = new Node[n];
+ var allNodes = new List<int>();
+ int counter = 0;
+ foreach (Node node in g.Nodes)
+ {
+ numberToNode[counter] = node;
+ nodeToNumber[node] = counter;
+ allNodes.Add(counter);
+ counter++;
}
- #endregion
- #region for all other predecessors, p, of b
- foreach (Node p in predecessors) {
- if (this.nodeToPostOrderNumber[p] == first_processed_predecessor) {
- continue;
- }
- if (this.doms[this.nodeToPostOrderNumber[p]] != 0)
- new_idom = intersect(this.nodeToPostOrderNumber[p], new_idom, this.doms);
+
+ var loops = new List<int>[n];
+ foreach (var h in g.Headers)
+ {
+ var loopNodes = new HashSet<Node>();
+ foreach (var b in g.BackEdgeNodes(h))
+ loopNodes.UnionWith(g.NaturalLoops(h, b));
+ loops[nodeToNumber[h]] =
+ new List<int>(loopNodes.Select(node => nodeToNumber[node]));
}
- #endregion
- if (this.doms[this.nodeToPostOrderNumber[b]] != new_idom) {
- this.doms[this.nodeToPostOrderNumber[b]] = new_idom;
- changed = true;
+
+ var successors = new List<int>[n];
+ int[] incomingEdges = new int[n];
+
+ foreach (var e in g.Edges)
+ {
+ Contract.Assert(e.Item1 != null);
+ Contract.Assert(e.Item2 != null);
+ int source = nodeToNumber[e.Item1], target = nodeToNumber[e.Item2];
+ if (loops[target] == null || !loops[target].Contains(source))
+ {
+ if (successors[source] == null)
+ successors[source] = new List<int>();
+ successors[source].Add(target);
+ incomingEdges[target]++;
+ }
}
- }
- }
- #region Populate the Immediate Dominator Map
- int sourceNum = this.nodeToPostOrderNumber[this.source];
- immediateDominatorMap = new Dictionary<Node, List<Node>>();
- for (int i = 1; i <= n; i++) {
- Node node = this.postOrderNumberToNode[i].Val;
- Node idomNode = this.postOrderNumberToNode[this.doms[i]].Val;
- if (i == sourceNum && this.doms[i] == sourceNum) {
- continue;
- }
- if (immediateDominatorMap.ContainsKey(idomNode)) {
- immediateDominatorMap[idomNode].Add(node);
- } else {
- List<Node> l = new List<Node>();
- l.Add(node);
- immediateDominatorMap.Add(idomNode, l);
- }
- }
- #endregion
- }
- private int intersect(int b1, int b2, int[] doms) {
- int finger1 = b1;
- int finger2 = b2;
- while (finger1 != finger2) {
- while (finger1 < finger2) {
- finger1 = doms[finger1];
- }
- while (finger2 < finger1) {
- finger2 = doms[finger2];
- }
- }
- return finger1;
- }
- private void PostOrderVisit(Node/*!*/ n, HashSet<Node> visited, ref int currentNumber) {
- Contract.Requires(n != null);
- if (visited.Contains(n))
- return;
- visited.Add(n);
- foreach (Node/*!*/ child in this.graph.Successors(n)) {
- Contract.Assert(child != null);
- PostOrderVisit(child, visited, ref currentNumber);
- }
- Contract.Assume(this.postOrderNumberToNode != null);
- Contract.Assume(this.nodeToPostOrderNumber != null);
- this.postOrderNumberToNode[currentNumber].Val = n;
- this.nodeToPostOrderNumber[n] = currentNumber;
- currentNumber++;
- return;
- }
- // Iterative version: mimics the above recursive procedure
- private void PostOrderVisitIterative(Node n)
- {
- Contract.Requires(n != null);
- var visited = new HashSet<Node>();
- var grey = new HashSet<Node>();
- var stack = new Stack<Node>();
-
- int currentNumber = 1;
-
- stack.Push(n);
- visited.Add(n);
-
- while (stack.Count != 0)
- {
- var curr = stack.Pop();
-
- if (grey.Contains(curr))
- {
- Contract.Assume(this.postOrderNumberToNode != null);
- Contract.Assume(this.nodeToPostOrderNumber != null);
- this.postOrderNumberToNode[currentNumber].Val = curr;
- this.nodeToPostOrderNumber[curr] = currentNumber;
- currentNumber++;
- }
- else
- {
- grey.Add(curr);
- stack.Push(curr);
- foreach (Node/*!*/ child in this.graph.Successors(curr))
- {
- Contract.Assert(child != null);
- if (!visited.Contains(child))
- {
- visited.Add(child);
- stack.Push(child);
- }
- }
- }
-
- }
-
-
- }
- }
- public class Graph<Node> {
- private HashSet<Tuple<Node/*!*/, Node/*!*/>> es;
- private HashSet<Node> ns;
- private Node source;
- private bool reducible;
- private HashSet<Node> headers;
- private Dictionary<Node, HashSet<Node>> backEdgeNodes;
- private Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops;
- private HashSet<Node> splitCandidates;
-
- private DomRelation<Node> dominatorMap = null;
- private Dictionary<Node, HashSet<Node>> predCache = new Dictionary<Node, HashSet<Node>>();
- private Dictionary<Node, HashSet<Node>> succCache = new Dictionary<Node, HashSet<Node>>();
- private bool predComputed;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(es == null || Contract.ForAll(es, p => p.Item1 != null && p.Item2 != null));
- Contract.Invariant(naturalLoops == null || Contract.ForAll(naturalLoops.Keys, p => p.Item2 != null && p.Item1 != null));
- }
-
- private class PreHeader {
- Node/*!*/ myHeader;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(myHeader != null);
- }
+ var sortedNodes = new List<Tuple<Node, bool>>();
+
+ var regionStack = new Stack<Tuple<Node, List<int>>>();
+ regionStack.Push(new Tuple<Node, List<int>>(default(Node), allNodes));
+
+ while (regionStack.Count != 0)
+ {
+ int rootIndex = -1;
+ foreach (var i in regionStack.Peek().Item2)
+ {
+ if (incomingEdges[i] == 0)
+ {
+ rootIndex = i;
+ break;
+ }
+ }
+ if (rootIndex == -1)
+ {
+ var region = regionStack.Pop();
+ if (regionStack.Count != 0)
+ sortedNodes.Add(new Tuple<Node, bool>(region.Item1, true));
+ continue;
+ }
+ incomingEdges[rootIndex] = -1;
+ sortedNodes.Add(new Tuple<Node, bool>(numberToNode[rootIndex], false));
+ if (successors[rootIndex] != null)
+ foreach (int s in successors[rootIndex])
+ incomingEdges[s]--;
+ if (loops[rootIndex] != null)
+ regionStack.Push(new Tuple<Node, List<int>>(numberToNode[rootIndex],
+ loops[rootIndex]));
+ }
- internal PreHeader(Node/*!*/ h) {
- Contract.Requires(h != null);
- myHeader = h;
+ return sortedNodes;
}
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return "#" + myHeader.ToString();
+ // Algorithm from Jeanne Ferrante, Karl J. Ottenstein, Joe D. Warren,
+ // "The Program Dependence Graph and Its Use in Optimization"
+ public static Dictionary<Node, HashSet<Node>> ControlDependence<Node>(this Graph<Node> g) where Node : class, new()
+ {
+ Graph<Node> dual = g.Dual(new Node());
+ DomRelation<Node> pdom = dual.DominatorMap;
+ var result = new Dictionary<Node, HashSet<Node>>();
+
+ var S = g.Edges.Where(e => !pdom.DominatedBy(e.Item1, e.Item2));
+ foreach (var edge in S)
+ {
+ var L = pdom.LeastCommonAncestor(edge.Item1, edge.Item2);
+ var deps = new List<Node>();
+ if (L == edge.Item1)
+ {
+ pdom.DominatedBy(edge.Item2, edge.Item1, deps);
+ deps.Add(edge.Item2);
+ deps.Add(edge.Item1);
+ }
+ else
+ {
+ pdom.DominatedBy(edge.Item2, L, deps);
+ deps.Add(edge.Item2);
+ }
+ if (result.ContainsKey(edge.Item1))
+ {
+ result[edge.Item1].UnionWith(deps);
+ }
+ else
+ {
+ result[edge.Item1] = new HashSet<Node>(deps);
+ }
+ }
+ return result;
}
- }
- public Graph(HashSet<Tuple<Node/*!*/, Node/*!*/>> edges) {
-
- Contract.Requires(cce.NonNullElements(edges) && Contract.ForAll(edges, p => p.Item1 != null && p.Item2 != null));
- es = edges;
+ }
- // original A#
- //ns = Set<Node>{ x : <x,y> in es } + Set<Node>{ y : <x,y> in es };
+ public delegate System.Collections.IEnumerable/*<Node!>*//*!*/ Adjacency<T>(T/*!*/ node);
- // closest Spec#
- //ns = new Set<Node>{ Tuple<Node,Node> p in edges; p.Item1 } + new Set<Node>{ Tuple<Node,Node> p in edges; p.Item2 };
- //
- HashSet<Node> temp = new HashSet<Node>();
- foreach (Tuple<Node/*!*/, Node/*!*/> p in edges) {
- Contract.Assert(p.Item1 != null);
- temp.Add(p.Item1);
- Contract.Assert(p.Item2 != null);
- temp.Add(p.Item2);
- }
- ns = temp;
- }
- public Graph() {
- es = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
- ns = new HashSet<Node>();
- }
-
- // BUGBUG: Set<T>.ToString() should return a non-null string
- [Pure]
- public override string/*!*/ ToString() {
- return "" + es.ToString();
- }
-
- public void AddSource(Node/*!*/ x) {
- Contract.Requires(x != null);
- // BUGBUG: This generates bad code in the compiler
- //ns += new Set<Node>{x};
- ns.Add(x);
- source = x;
- }
-
- public void AddEdge(Node/*!*/ source, Node/*!*/ dest) {
- Contract.Requires(source != null);
- Contract.Requires(dest != null);
- //es += Set<Edge>{<source,dest>};
- //ns += Set<Node>{source, dest};
- es.Add(new Tuple<Node/*!*/, Node/*!*/>(source, dest));
- ns.Add(source);
- ns.Add(dest);
- predComputed = false;
- }
-
- public HashSet<Node> Nodes {
- get {
- return ns;
+ // An SCC is a set of nodes
+ public sealed class SCC<Node> : ICollection<Node>
+ {
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(nodesMap != null);
}
- }
- public IEnumerable<Tuple<Node/*!*/, Node/*!*/>> Edges {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<Tuple<Node, Node>>>())
- && Contract.ForAll(Contract.Result<IEnumerable<Tuple<Node, Node>>>(), n =>
- n.Item1 != null && n.Item2 != null));
- return es;
+
+ private IDictionary<Node, object>/*!*/ nodesMap = new Dictionary<Node, object>();
+ private ICollection<Node>/*!*/ nodes
+ {
+ get
+ {
+ return cce.NonNull(nodesMap.Keys);
+ }
}
- }
-
- public bool Edge(Node/*!*/ x, Node/*!*/ y) {
- Contract.Requires(x != null);
- Contract.Requires(y != null);
- // original A#
- // return <x,y> in es;
- return es.Contains(new Tuple<Node/*!*/, Node/*!*/>(x, y));
- }
-
- private void ComputePredSuccCaches() {
- if (predComputed)
- return;
- predComputed = true;
- predCache = new Dictionary<Node, HashSet<Node>>();
- succCache = new Dictionary<Node, HashSet<Node>>();
-
- foreach (Node n in Nodes) {
- predCache[n] = new HashSet<Node>();
- succCache[n] = new HashSet<Node>();
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ System.Collections.IEnumerator/*!*/ System.Collections.IEnumerable.GetEnumerator()
+ {
+ Contract.Ensures(Contract.Result<System.Collections.IEnumerator>() != null);
+
+ return ((System.Collections.IEnumerable)nodes).GetEnumerator();
}
- foreach (Tuple<Node/*!*/, Node/*!*/> p in Edges) {
- Contract.Assert(p.Item1 != null);
- Contract.Assert(p.Item2 != null);
- HashSet<Node> tmp;
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ IEnumerator<Node>/*!*/ IEnumerable<Node>.GetEnumerator()
+ {
+ Contract.Ensures(Contract.Result<IEnumerator<Node>>() != null);
- tmp = predCache[p.Item2];
- tmp.Add(p.Item1);
- predCache[p.Item2] = tmp;
+ return ((IEnumerable<Node>)nodes).GetEnumerator();
+ }
- tmp = succCache[p.Item1];
- tmp.Add(p.Item2);
- succCache[p.Item1] = tmp;
+ public int Count
+ {
+ get
+ {
+ return nodes.Count;
+ }
}
- }
-
- public IEnumerable<Node> Predecessors(Node n) {
- // original A#
- //Set<Node> result = Set{ x : x in Nodes, Edge(x,n) };
-
- ComputePredSuccCaches();
- return predCache[n];
- }
-
- public IEnumerable<Node> Successors(Node n) {
- ComputePredSuccCaches();
- return succCache[n];
- }
-
- public List<Node> SuccessorsAsList(Node n) {
- ComputePredSuccCaches();
- List<Node> ret = new List<Node>();
- foreach (Node s in succCache[n])
- ret.Add(s);
- return ret;
- }
-
- public DomRelation<Node> /*Map<Node,Set<Node>>*/ DominatorMap {
- get {
- Contract.Assert(source != null);
- if (this.dominatorMap == null) {
- this.dominatorMap = new DomRelation<Node>(this, this.source);
- }
- return this.dominatorMap;
+ public bool IsReadOnly
+ {
+ get
+ {
+ return nodesMap.IsReadOnly;
+ }
}
- }
-
- public Dictionary<Node, List<Node>> ImmediateDominatorMap {
- get {
- Contract.Assert(source != null);
- if (this.dominatorMap == null) {
- this.dominatorMap = new DomRelation<Node>(this, this.source);
- }
- return this.dominatorMap.ImmediateDominatorMap;
+ public void Add(Node item)
+ {
+ nodesMap.Add(item, null);
}
- }
- public List<Node> ImmediatelyDominatedBy(Node/*!*/ n) {
- Contract.Requires(n != null);
- List<Node> dominees;
- this.ImmediateDominatorMap.TryGetValue(n, out dominees);
- return dominees == null ? new List<Node>() : dominees;
- }
-
- public IEnumerable<Node/*?*/> TopologicalSort() {
- bool acyclic;
- List<Node> sortedList;
- this.TarjanTopSort(out acyclic, out sortedList);
- return acyclic ? sortedList : new List<Node>();
- }
- // From Tarjan 1972
- public void TarjanTopSort(out bool acyclic, out List<Node> sortedNodes) {
- int n = this.Nodes.Count;
- if (n == 0) {
- acyclic = true;
- sortedNodes = new List<Node>();
- return;
+ public void Clear()
+ {
+ nodesMap.Clear();
}
- int[] incomingEdges = new int[n];
- // need an arbitrary numbering for the nodes to use as indices into
- // the arrays used within this algorithm
- Dictionary<Node, int> nodeToNumber = new Dictionary<Node, int>(n);
- Maybe<Node>[] numberToNode = new Maybe<Node>[n];
- int counter = 0;
- foreach (Node node in this.Nodes) {
- numberToNode[counter].Val = node;
- nodeToNumber[node] = counter;
- counter++;
+ [Pure]
+ public bool Contains(Node item)
+ {
+ return nodesMap.ContainsKey(item);
}
- foreach (Tuple<Node/*!*/, Node/*!*/> e in this.Edges) {
- Contract.Assert(e.Item1 != null);
- Contract.Assert(e.Item2 != null);
- Node/*!*/ target = e.Item2;
- incomingEdges[nodeToNumber[target]]++;
+ public void CopyTo(Node[] array, int arrayIndex)
+ {
+ //Contract.Requires(array != null);
+ nodes.CopyTo(array, arrayIndex);
}
- List<Node> sorted = new List<Node>();
- int sortedIndex = 0;
- while (sortedIndex < n) {
- // find a root (i.e., its index)
- int rootIndex = -1;
- for (int i = 0; i < n; i++) {
- if (incomingEdges[i] == 0) {
- rootIndex = i;
- break;
- }
- }
- if (rootIndex == -1) {
- acyclic = false;
- sortedNodes = new List<Node>();
- return;
- }
- // mark root so it won't be used again
- incomingEdges[rootIndex] = -1;
- Node root = numberToNode[rootIndex].Val;
- sorted.Add(root);
- ++sortedIndex;
- foreach (Node s in this.Successors(root)) {
- incomingEdges[nodeToNumber[s]]--;
- }
+ public bool Remove(Node item)
+ {
+ return nodesMap.Remove(item);
}
- acyclic = true;
- sortedNodes = sorted;
- return;
- }
- private IEnumerable<Node> OldTopologicalSort() {
- Tuple<bool, List<Node>> result = this.TopSort();
- return result.Item1 ? result.Item2 : (IEnumerable<Node>)new List<Node>();
- }
- // From AsmL distribution example
- private Tuple<bool, List<Node>> TopSort()
- {
- List<Node> S = new List<Node>();
- HashSet<Node> V = this.Nodes;
- HashSet<Node> X = new HashSet<Node>();
- foreach (Node/*!*/ n in V) {
- Contract.Assert(n != null);
- X.Add(n);
+ }
+
+ public sealed class StronglyConnectedComponents<Node> : IEnumerable<SCC<Node>/*!*/> where Node : class
+ {
+ private readonly IDictionary<Node/*!*/, object>/*!*/ graph;
+ [ContractInvariantMethod]
+ void graphInvariantMethod()
+ {
+ Contract.Invariant(Contract.ForAll(graph, entry => entry.Key != null));
+ Contract.Invariant(preds != null);
+ Contract.Invariant(succs != null);
}
- bool change = true;
- while (change)
- // invariant: X = V - S
- {
- change = false;
- if (X.Count > 0) {
- foreach (Node/*!*/ n in X) {
- Contract.Assert(n != null);
- // see if n has any incoming edges from any other node in X
- bool inDegreeZero = true;
- foreach (Node/*!*/ u in X) {
- Contract.Assert(u != null);
- if (this.Edge(u, n)) {
- inDegreeZero = false;
- break; // no point looking further
- }
- }
- if (inDegreeZero) {
- S.Add(n);
- X.Remove(n);
- change = true;
- break; // might as well go back and start looking through X from the beginning
- }
+ private readonly Adjacency<Node>/*!*/ preds;
+ private readonly Adjacency<Node>/*!*/ succs;
+
+ private bool computed = false;
+ public bool Computed
+ {
+ get
+ {
+ return computed;
}
- // Then we made it all the way through X without finding a source node
- if (!change) {
- return new Tuple<bool, List<Node>>(false, new List<Node>());
+ }
+
+ [NotDelayed]
+ public StronglyConnectedComponents(System.Collections.IEnumerable/*<Node!>*/ graph, Adjacency<Node> preds, Adjacency<Node> succs)
+ : base()
+ {//BASEMOVE DANGER
+ Contract.Requires(succs != null);
+ Contract.Requires(preds != null);
+ Contract.Requires(graph != null);
+ Contract.Ensures(!Computed);
+ IDictionary<Node/*!*/, object>/*!*/ dict = new Dictionary<Node/*!*/, object>();
+ foreach (Node/*!*/ n in graph)
+ {
+ Contract.Assert(n != null);
+ dict.Add(n, null);
}
- }
+
+ this.graph = dict;
+ this.preds = preds;
+ this.succs = succs;
+ //:base();
}
- return new Tuple<bool, List<Node>>(true, S);
- }
-
- public static bool Acyclic(Graph<Node> g, Node source) {
- bool acyclic;
- List<Node> sortedList;
- g.TarjanTopSort(out acyclic, out sortedList);
- return acyclic;
- }
-
- // [Dragon, Fig. 10.15, p. 604. Algorithm for constructing the natural loop.]
- static HashSet<Node> NaturalLoop(Graph<Node> g, Tuple<Node/*!*/, Node/*!*/> backEdge)
- {
- Contract.Requires(backEdge.Item1 != null && backEdge.Item2 != null);
- Node/*!*/ n = backEdge.Item1;
- Node/*!*/ d = backEdge.Item2;
- Stack<Node> stack = new Stack<Node>();
- HashSet<Node> loop = new HashSet<Node>();
- loop.Add(d);
- if (!n.Equals(d)) // then n is not in loop
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ System.Collections.IEnumerator/*!*/ System.Collections.IEnumerable.GetEnumerator()
{
- loop.Add(n);
- stack.Push(n); // push n onto stack
+ Contract.Ensures(Contract.Result<System.Collections.IEnumerator>() != null);
+
+ return ((System.Collections.IEnumerable)sccs).GetEnumerator();
}
- while (stack.Count > 0) // not empty
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ IEnumerator<SCC<Node>/*!*/>/*!*/ IEnumerable<SCC<Node>/*!*/>.GetEnumerator()
{
- Node m = stack.Peek();
- stack.Pop(); // pop stack
- foreach (Node/*!*/ p in g.Predecessors(m)) {
- Contract.Assert(p != null);
- if (!(loop.Contains(p))) {
- loop.Add(p);
- stack.Push(p); // push p onto stack
- }
- }
+ Contract.Ensures(Contract.Result<IEnumerator<SCC<Node>>>() != null);
+
+ Contract.Assume(Computed);
+ Contract.Assert(cce.NonNullElements((IEnumerable<SCC<Node>/*!*/>)sccs));//REVIEW
+ return ((IEnumerable<SCC<Node>/*!*/>)sccs).GetEnumerator();
}
- return loop;
- }
-
- internal struct ReducibleResult {
- internal bool reducible;
- internal HashSet<Node> headers;
- internal Dictionary<Node, HashSet<Node>> backEdgeNodes;
- internal Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops;
- internal HashSet<Node> splitCandidates;
+
+ private readonly IList<SCC<Node>/*!*/>/*!*/ sccs = new List<SCC<Node>/*!*/>();
[ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Contract.ForAll(naturalLoops.Keys, p => p.Item1 != null && p.Item2 != null));
+ void sccsInvariant()
+ {
+ Contract.Invariant(cce.NonNullElements(sccs));
}
- internal ReducibleResult(bool b, HashSet<Node> headers, Dictionary<Node, HashSet<Node>> backEdgeNodes, Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops, HashSet<Node> splitCandidates)
+
+ public void Compute()
{
- Contract.Requires(naturalLoops == null || Contract.ForAll(naturalLoops.Keys, Key => Key.Item1 != null && Key.Item2 != null));
- this.reducible = b;
- this.headers = headers;
- this.backEdgeNodes = backEdgeNodes;
- this.naturalLoops = naturalLoops;
- this.splitCandidates = splitCandidates;
- }
+ Contract.Requires(!Computed);
+ Contract.Ensures(Computed);
+ // Compute post times on graph with edges reversed
+ this.dfsNext = this.preds;
+ foreach (Node/*!*/ n in cce.NonNull(graph.Keys))
+ {
+ Contract.Assert(n != null);
+ if (!seen.ContainsKey(n))
+ {
+ OrderNodes(n);
+ }
+ }
- }
-
- // [Dragon, p. 606]
- static ReducibleResult ComputeReducible(Graph<Node> g, Node source) {
- // first, compute the dom relation
- DomRelation<Node> /*Map<Node,Set<Node>>*/ D = g.DominatorMap;
- return ComputeReducible(g, source, D);
- }
-
- static HashSet<Node> FindCycle(Graph<Node> g, Node source) {
- Stack<Tuple<Node, List<Node>>> stack = new Stack<Tuple<Node, List<Node>>>();
- HashSet<Node> stackAsSet = new HashSet<Node>();
- HashSet<Node> visited = new HashSet<Node>();
- stack.Push(new Tuple<Node, List<Node>>(source, g.SuccessorsAsList(source)));
- stackAsSet.Add(source);
- while (stack.Count > 0) {
- Tuple<Node, List<Node>> tuple = stack.Peek();
- List<Node> children = tuple.Item2;
- if (children.Count == 0) {
- stack.Pop();
- stackAsSet.Remove(tuple.Item1);
- continue;
- }
- Node n = children[0];
- children.RemoveAt(0);
- if (stackAsSet.Contains(n)) {
- HashSet<Node> ret = new HashSet<Node>();
- ret.Add(n);
- while (true) {
- Node x = stack.Pop().Item1;
- if (x.Equals(n))
- return ret;
+ // Clear seen
+ seen.Clear();
+
+ // Compute SCCs
+ this.dfsNext = this.succs;
+ while (postOrder.Count > 0)
+ {
+ Node/*!*/ n = postOrder.Pop();
+ Contract.Assert(n != null);
+
+ if (!seen.ContainsKey(n))
+ {
+ SCC<Node>/*!*/ curr = new SCC<Node>();
+ FindSCCs(n, curr);
+ sccs.Add(curr);
+ }
}
- }
- if (visited.Contains(n))
- continue;
- stack.Push(new Tuple<Node, List<Node>>(n, g.SuccessorsAsList(n)));
- visited.Add(n);
- stackAsSet.Add(n);
- System.Diagnostics.Debug.Assert(stack.Count == stackAsSet.Count);
+
+ // Clear seen
+ seen.Clear();
+
+ this.computed = true;
}
- return new HashSet<Node>();
- }
-
- // [Dragon, p. 606]
- static ReducibleResult ComputeReducible(Graph<Node> g,
- Node source,
- DomRelation<Node>/*!*/ DomRelation) {
- Contract.Requires(DomRelation != null);
-
- //Console.WriteLine("[" + DateTime.Now +"]: begin ComputeReducible");
- IEnumerable<Tuple<Node/*!*/, Node/*!*/>> edges = g.Edges;
- Contract.Assert(Contract.ForAll(edges, n => n.Item1 != null && n.Item2 != null));
- HashSet<Tuple<Node/*!*/, Node/*!*/>> backEdges = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
- HashSet<Tuple<Node/*!*/, Node/*!*/>> nonBackEdges = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
- foreach (Tuple<Node/*!*/, Node/*!*/> e in edges) {
- Contract.Assert(e.Item1 != null);
- Contract.Assert(e.Item2 != null);
- Node x = e.Item1;
- Node y = e.Item2; // so there is an edge from x to y
- if (DomRelation.DominatedBy(x, y)) { // y dom x: which means y dominates x
- backEdges.Add(e);
- } else {
- nonBackEdges.Add(e);
- }
+
+ private Adjacency<Node>/*?*/ dfsNext = null;
+
+ private readonly IDictionary<Node/*!*/, object>/*!*/ seen = new Dictionary<Node/*!*/, object>();
+ private readonly Stack<Node/*!*/>/*!*/ postOrder = new Stack<Node/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(seen != null);
+ Contract.Invariant(cce.NonNullElements(postOrder));
}
- Graph<Node> withoutBackEdges = new Graph<Node>(nonBackEdges);
- if (!Acyclic(withoutBackEdges, source)) {
- return new ReducibleResult(false,
- new HashSet<Node>(),
- new Dictionary<Node, HashSet<Node>>(),
- new Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>>(),
- FindCycle(withoutBackEdges, source));
- } else {
- // original A#:
- //Set<Node> headers = Set{ d : <n,d> in backEdges };
- HashSet<Node> headers = new HashSet<Node>();
- foreach (Tuple<Node/*!*/, Node/*!*/> e in backEdges) {
-
- Contract.Assert(e.Item1 != null);
- Contract.Assert(e.Item2 != null);
- headers.Add(e.Item2);
- }
- // original A#:
- //Map<Node,Set<Node>> backEdgeNodes = Map{ h -> bs : h in headers, bs = Set<Node>{ b : <b,x> in backEdges, x == h } };
- Dictionary<Node, HashSet<Node>> backEdgeNodes = new Dictionary<Node, HashSet<Node>>();
- foreach (Node/*!*/ h in headers) {
- Contract.Assert(h != null);
- HashSet<Node> bs = new HashSet<Node>();
- foreach (Tuple<Node, Node> backedge in backEdges) {
- Contract.Assert(backedge.Item1 != null);
- Contract.Assert(backedge.Item2 != null);
- if (backedge.Item2.Equals(h)) {
- bs.Add(backedge.Item1);
- }
+
+
+ // DFS to order nodes by post times
+ private void OrderNodes(Node node)
+ {
+ Contract.Requires(node != null);
+ seen.Add(node, null);
+
+ Contract.Assert(dfsNext != null);
+ System.Collections.IEnumerable/*!*/ nexts = dfsNext(node);
+ Contract.Assert(nexts != null);
+ foreach (Node/*!*/ n in nexts)
+ {
+ Contract.Assert(n != null);
+ if (graph.ContainsKey(n) && !seen.ContainsKey(n))
+ {
+ OrderNodes(n);
+ }
}
- backEdgeNodes.Add(h, bs);
- }
-
- // original A#:
- //Map<Tuple<Node,Node>,Set<Node>> naturalLoops = Map{ e -> NaturalLoop(g,e) : e in backEdges };
- Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops = new Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>>();
- foreach (Tuple<Node/*!*/, Node/*!*/> e in backEdges) {
- Contract.Assert(e.Item1 != null && e.Item2 != null);
- naturalLoops.Add(e, NaturalLoop(g, e));
- }
-
- //Console.WriteLine("[" + DateTime.Now +"]: end ComputeReducible");
- return new ReducibleResult(true, headers, backEdgeNodes, naturalLoops, new HashSet<Node>());
- }
- }
- public bool Reducible {
- get {
- return reducible;
+ postOrder.Push(node);
}
- }
- public IEnumerable<Node> Headers {
- get {
- return headers;
- }
- }
- public IEnumerable<Node> BackEdgeNodes(Node/*!*/ h) {
- Contract.Requires(h != null);
- // original A#:
- //return h in backEdgeNodes ? backEdgeNodes[h] : null;
- return (backEdgeNodes.ContainsKey(h) ? backEdgeNodes[h] : (IEnumerable<Node>)new List<Node>());
- }
- public IEnumerable<Node> NaturalLoops(Node/*!*/ header, Node/*!*/ backEdgeNode) {
- Contract.Requires(header != null);
- Contract.Requires(backEdgeNode != null);
- Tuple<Node/*!*/, Node/*!*/> e = new Tuple<Node/*!*/, Node/*!*/>(backEdgeNode, header);
- return naturalLoops.ContainsKey(e) ? naturalLoops[e] : (IEnumerable<Node>)new List<Node>();
- }
- public HashSet<Node> SplitCandidates {
- get {
- return splitCandidates;
+
+ // DFS to compute SCCs
+ private void FindSCCs(Node node, SCC<Node> currSCC)
+ {
+ Contract.Requires(currSCC != null);
+ Contract.Requires(node != null);
+ //modifies currSCC.*;
+ seen.Add(node, null);
+ currSCC.Add(node);
+
+ Contract.Assert(dfsNext != null);
+ System.Collections.IEnumerable/*!*/ nexts = dfsNext(node);
+ Contract.Assert(nexts != null);
+ foreach (Node/*!*/ n in nexts)
+ {
+ Contract.Assert(n != null);
+ if (graph.ContainsKey(n) && !seen.ContainsKey(n))
+ {
+ FindSCCs(n, currSCC);
+ }
+ }
}
- }
- public void ComputeLoops() {
- ReducibleResult r = ComputeReducible(this, this.source);
- this.reducible = r.reducible;
- this.headers = r.headers;
- this.backEdgeNodes = r.backEdgeNodes;
- this.naturalLoops = r.naturalLoops;
- this.splitCandidates = r.splitCandidates;
- return;
- }
-
- public IEnumerable<Node> SortHeadersByDominance()
- {
- Graph<Node> dag = new Graph<Node>();
- foreach (Node b in headers)
- {
- dag.AddSource(b);
- foreach (Node c in headers)
- {
- if (b.Equals(c)) continue;
- if (DominatorMap.DominatedBy(b, c))
- {
- System.Diagnostics.Debug.Assert(!DominatorMap.DominatedBy(c, b));
- dag.AddEdge(b, c);
- }
- }
- }
- return dag.TopologicalSort();
- }
-
- public string ToDot(Func<Node, string> NodeLabel = null, Func<Node, string> NodeStyle = null) {
- NodeLabel = NodeLabel ?? (n => n.ToString());
- NodeStyle = NodeStyle ?? (n => "[shape=box]");
- var s = new StringBuilder();
- s.AppendLine("digraph G {");
- foreach (var n in Nodes)
- s.AppendLine(" \"" + NodeLabel(n) + "\" " + NodeStyle(n) + ";");
- foreach (var e in Edges)
- s.AppendLine(" \"" + NodeLabel(e.Item1) + "\" -> \"" + NodeLabel(e.Item2) + "\";");
- s.AppendLine("}");
- return s.ToString();
- }
- } // end: class Graph
- public class GraphProgram {
- static void TestGraph<T>(T/*!*/ source, params Tuple<T/*!*/, T/*!*/>[] edges) {
- Contract.Requires(source != null);
- Contract.Requires(Contract.ForAll(edges, pair => pair.Item1 != null && pair.Item2 != null));
- HashSet<Tuple<T/*!*/, T/*!*/>> es = new HashSet<Tuple<T/*!*/, T/*!*/>>();
- foreach (Tuple<T/*!*/, T/*!*/> e in edges) {
- Contract.Assert(e.Item1 != null && e.Item2 != null);
- es.Add(e);
+ [Pure]
+ public override string ToString()
+ {
+ Contract.Ensures(Contract.Result<string>() != null);
+ string outStr = "";
+ int i = 0;
+
+ foreach (ICollection<Node> component in this)
+ {
+ string/*!*/ tmp = System.String.Format("\nComponent #{0} = ", i++);
+ Contract.Assert(tmp != null);
+ outStr += tmp;
+
+ bool firstInRow = true;
+
+ foreach (Node b in component)
+ {
+ string/*!*/ tmpComponent = System.String.Format("{0}{1}", firstInRow ? "" : ", ", b);
+ Contract.Assert(tmpComponent != null);
+ outStr += tmpComponent;
+ firstInRow = false;
+ }
+ }
+ return outStr;
}
- Graph<T> g = new Graph<T>(es);
- g.AddSource(source);
- Console.WriteLine("G = " + g);
- g.ComputeLoops();
- Console.WriteLine("G's Dominator Map = " + g.DominatorMap);
- Console.WriteLine("G's Immediate Dominator Map = " + Util.MapToString(g.ImmediateDominatorMap));
- Console.WriteLine("G is reducible: " + (g.Reducible ? "yes" : "no"));
- }
-
- static void Main(string[] args)
- //requires forall{string s in args; s != null};
- {
- Console.WriteLine("Spec# says hello!");
- // This generates bad IL -- need to fix a bug in the compiler
- //Graph<int> g = new Graph<int>(new Set<Tuple<int,int>>{ new Tuple<int,int>(1,2), new Tuple<int,int>(1,3), new Tuple<int,int>(2,3) });
-
- Console.WriteLine("");
- TestGraph<char>('a',
- new Tuple<char, char>('a', 'b'),
- new Tuple<char, char>('a', 'c'),
- new Tuple<char, char>('b', 'c')
- );
-
- Console.WriteLine("");
- TestGraph<char>('a',
- new Tuple<char, char>('a', 'b'),
- new Tuple<char, char>('a', 'c'),
- new Tuple<char, char>('b', 'd'),
- new Tuple<char, char>('c', 'e'),
- new Tuple<char, char>('c', 'f'),
- new Tuple<char, char>('d', 'e'),
- new Tuple<char, char>('e', 'd'),
- new Tuple<char, char>('e', 'f'),
- new Tuple<char, char>('f', 'e')
- );
-
- Console.WriteLine("");
- TestGraph<char>('a',
- new Tuple<char, char>('a', 'b'),
- new Tuple<char, char>('a', 'c'),
- new Tuple<char, char>('b', 'c'),
- new Tuple<char, char>('c', 'b')
- );
-
- Console.WriteLine("");
- TestGraph<int>(1,
- new Tuple<int, int>(1, 2),
- new Tuple<int, int>(1, 3),
- new Tuple<int, int>(2, 3)
- );
-
- Console.WriteLine("");
- TestGraph<int>(1,
- new Tuple<int, int>(1, 2),
- new Tuple<int, int>(1, 3),
- new Tuple<int, int>(2, 3),
- new Tuple<int, int>(3, 2)
- );
-
- Console.WriteLine("");
- TestGraph<int>(2,
- new Tuple<int, int>(2, 3),
- new Tuple<int, int>(2, 4),
- new Tuple<int, int>(3, 2)
- );
-
- Console.WriteLine("");
- TestGraph<char>('a',
- new Tuple<char, char>('a', 'b'),
- new Tuple<char, char>('a', 'c'),
- new Tuple<char, char>('b', 'c'),
- new Tuple<char, char>('b', 'b')
- );
-
-
- }
- }
-}
+ }
+
+ public class GraphProgram {
+ static void TestGraph<T>(T/*!*/ source, params Tuple<T/*!*/, T/*!*/>[] edges) {
+ Contract.Requires(source != null);
+ Contract.Requires(Contract.ForAll(edges, pair => pair.Item1 != null && pair.Item2 != null));
+ HashSet<Tuple<T/*!*/, T/*!*/>> es = new HashSet<Tuple<T/*!*/, T/*!*/>>();
+ foreach (Tuple<T/*!*/, T/*!*/> e in edges) {
+ Contract.Assert(e.Item1 != null && e.Item2 != null);
+ es.Add(e);
+ }
+ Graph<T> g = new Graph<T>(es);
+ g.AddSource(source);
+ Console.WriteLine("G = " + g);
+ g.ComputeLoops();
+ Console.WriteLine("G's Dominator Map = " + g.DominatorMap);
+ Console.WriteLine("G's Immediate Dominator Map = " + Util.MapToString(g.ImmediateDominatorMap));
+ Console.WriteLine("G is reducible: " + (g.Reducible ? "yes" : "no"));
+ }
+
+ static void Main(string[] args)
+ //requires forall{string s in args; s != null};
+ {
+ Console.WriteLine("Spec# says hello!");
+ // This generates bad IL -- need to fix a bug in the compiler
+ //Graph<int> g = new Graph<int>(new Set<Tuple<int,int>>{ new Tuple<int,int>(1,2), new Tuple<int,int>(1,3), new Tuple<int,int>(2,3) });
+
+ Console.WriteLine("");
+ TestGraph<char>('a',
+ new Tuple<char, char>('a', 'b'),
+ new Tuple<char, char>('a', 'c'),
+ new Tuple<char, char>('b', 'c')
+ );
+
+ Console.WriteLine("");
+ TestGraph<char>('a',
+ new Tuple<char, char>('a', 'b'),
+ new Tuple<char, char>('a', 'c'),
+ new Tuple<char, char>('b', 'd'),
+ new Tuple<char, char>('c', 'e'),
+ new Tuple<char, char>('c', 'f'),
+ new Tuple<char, char>('d', 'e'),
+ new Tuple<char, char>('e', 'd'),
+ new Tuple<char, char>('e', 'f'),
+ new Tuple<char, char>('f', 'e')
+ );
+
+ Console.WriteLine("");
+ TestGraph<char>('a',
+ new Tuple<char, char>('a', 'b'),
+ new Tuple<char, char>('a', 'c'),
+ new Tuple<char, char>('b', 'c'),
+ new Tuple<char, char>('c', 'b')
+ );
+
+ Console.WriteLine("");
+ TestGraph<int>(1,
+ new Tuple<int, int>(1, 2),
+ new Tuple<int, int>(1, 3),
+ new Tuple<int, int>(2, 3)
+ );
+
+ Console.WriteLine("");
+ TestGraph<int>(1,
+ new Tuple<int, int>(1, 2),
+ new Tuple<int, int>(1, 3),
+ new Tuple<int, int>(2, 3),
+ new Tuple<int, int>(3, 2)
+ );
+
+ Console.WriteLine("");
+ TestGraph<int>(2,
+ new Tuple<int, int>(2, 3),
+ new Tuple<int, int>(2, 4),
+ new Tuple<int, int>(3, 2)
+ );
+
+ Console.WriteLine("");
+ TestGraph<char>('a',
+ new Tuple<char, char>('a', 'b'),
+ new Tuple<char, char>('a', 'c'),
+ new Tuple<char, char>('b', 'c'),
+ new Tuple<char, char>('b', 'b')
+ );
+
+
+ }
+ }
+
+}
diff --git a/Source/Houdini/Houdini.cs b/Source/Houdini/Houdini.cs
index b47512bd..5271a6a3 100644
--- a/Source/Houdini/Houdini.cs
+++ b/Source/Houdini/Houdini.cs
@@ -11,8 +11,7 @@ using Microsoft.Boogie.VCExprAST;
using VC;
using System.Collections;
using System.IO;
-using Microsoft.AbstractInterpretationFramework;
-using Graphing;
+using Microsoft.Boogie.GraphUtil;
namespace Microsoft.Boogie.Houdini {
@@ -485,17 +484,18 @@ namespace Microsoft.Boogie.Houdini {
public bool MatchCandidate(Expr boogieExpr, out Variable candidateConstant) {
candidateConstant = null;
- IExpr antecedent, consequent;
- IExpr expr = boogieExpr as IExpr;
- if (expr != null && ExprUtil.Match(expr, Prop.Implies, out antecedent, out consequent)) {
- IdentifierExpr.ConstantFunApp constantFunApp = antecedent as IdentifierExpr.ConstantFunApp;
- if (constantFunApp != null && houdiniConstants.Contains(constantFunApp.IdentifierExpr.Decl)) {
- candidateConstant = constantFunApp.IdentifierExpr.Decl;
+ NAryExpr e = boogieExpr as NAryExpr;
+ if (e != null && e.Fun is BinaryOperator && ((BinaryOperator)e.Fun).Op == BinaryOperator.Opcode.Imp) {
+ Expr antecedent = e.Args[0];
+ Expr consequent = e.Args[1];
+
+ IdentifierExpr id = antecedent as IdentifierExpr;
+ if (id != null && id.Decl is Constant && houdiniConstants.Contains((Constant)id.Decl)) {
+ candidateConstant = id.Decl;
return true;
}
- var e = consequent as Expr;
- if (e != null && MatchCandidate(e, out candidateConstant))
+ if (MatchCandidate(consequent, out candidateConstant))
return true;
}
return false;
diff --git a/Source/Houdini/Houdini.csproj b/Source/Houdini/Houdini.csproj
index af1755a3..97d26001 100644
--- a/Source/Houdini/Houdini.csproj
+++ b/Source/Houdini/Houdini.csproj
@@ -82,10 +82,6 @@
<Compile Include="Houdini.cs" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
<ProjectReference Include="..\Basetypes\Basetypes.csproj">
<Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
<Name>Basetypes</Name>
diff --git a/Source/VCGeneration/BlockPredicator.cs b/Source/Predication/BlockPredicator.cs
index 9df1c086..8419471e 100644
--- a/Source/VCGeneration/BlockPredicator.cs
+++ b/Source/Predication/BlockPredicator.cs
@@ -1,4 +1,4 @@
-using Graphing;
+using Microsoft.Boogie.GraphUtil;
using System;
using System.Collections.Generic;
using System.Diagnostics;
diff --git a/Source/Predication/Predication.csproj b/Source/Predication/Predication.csproj
new file mode 100644
index 00000000..8060f52f
--- /dev/null
+++ b/Source/Predication/Predication.csproj
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Predication</RootNamespace>
+ <AssemblyName>Predication</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BlockPredicator.cs" />
+ <Compile Include="SmartBlockPredicator.cs" />
+ <Compile Include="UniformityAnalyser.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43dfad18-3e35-4558-9be2-caff6b5ba8a0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{b230a69c-c466-4065-b9c1-84d80e76d802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Graph\Graph.csproj">
+ <Project>{69a2b0b8-bcac-4101-ae7a-556fcc58c06e}</Project>
+ <Name>Graph</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{fcd3ac7f-9dfd-46c8-ab1e-09f0b0f16dc5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
+ <Project>{e1f10180-c7b9-4147-b51f-fa1b701966dc}</Project>
+ <Name>VCGeneration</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Source/VCGeneration/SmartBlockPredicator.cs b/Source/Predication/SmartBlockPredicator.cs
index f769822c..9478595b 100644
--- a/Source/VCGeneration/SmartBlockPredicator.cs
+++ b/Source/Predication/SmartBlockPredicator.cs
@@ -1,4 +1,4 @@
-using Graphing;
+using Microsoft.Boogie.GraphUtil;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -14,7 +14,7 @@ public class SmartBlockPredicator {
Graph<Block> blockGraph;
List<Tuple<Block, bool>> sortedBlocks;
- bool useProcedurePredicates = true;
+ Func<Procedure, bool> useProcedurePredicates;
Dictionary<Block, Variable> predMap, defMap;
Dictionary<Block, HashSet<Variable>> ownedMap;
@@ -26,15 +26,26 @@ public class SmartBlockPredicator {
new Dictionary<Microsoft.Boogie.Type, IdentifierExpr>();
Dictionary<Block, Expr> blockIds = new Dictionary<Block, Expr>();
HashSet<Block> doneBlocks = new HashSet<Block>();
+ bool myUseProcedurePredicates;
+ UniformityAnalyser uni;
- SmartBlockPredicator(Program p, Implementation i, bool upp) {
+ SmartBlockPredicator(Program p, Implementation i, Func<Procedure, bool> upp, UniformityAnalyser u) {
prog = p;
impl = i;
useProcedurePredicates = upp;
+ myUseProcedurePredicates = useProcedurePredicates(i.Proc);
+ uni = u;
}
void PredicateCmd(Expr p, List<Block> blocks, Block block, Cmd cmd, out Block nextBlock) {
- if (!useProcedurePredicates && cmd is CallCmd) {
+ var cCmd = cmd as CallCmd;
+ if (cCmd != null && !useProcedurePredicates(cCmd.Proc)) {
+ if (p == null) {
+ block.Cmds.Add(cmd);
+ nextBlock = block;
+ return;
+ }
+
var trueBlock = new Block();
blocks.Add(trueBlock);
trueBlock.Label = block.Label + ".call.true";
@@ -62,12 +73,14 @@ public class SmartBlockPredicator {
}
void PredicateCmd(Expr p, CmdSeq cmdSeq, Cmd cmd) {
- if (p == null) {
+ if (cmd is CallCmd) {
+ var cCmd = (CallCmd)cmd;
+ Debug.Assert(useProcedurePredicates(cCmd.Proc));
+ cCmd.Ins.Insert(0, p != null ? p : Expr.True);
+ cmdSeq.Add(cCmd);
+ } else if (p == null) {
cmdSeq.Add(cmd);
- return;
- }
-
- if (cmd is AssignCmd) {
+ } else if (cmd is AssignCmd) {
var aCmd = (AssignCmd)cmd;
cmdSeq.Add(new AssignCmd(Token.NoToken, aCmd.Lhss,
new List<Expr>(aCmd.Lhss.Zip(aCmd.Rhss, (lhs, rhs) =>
@@ -106,31 +119,31 @@ public class SmartBlockPredicator {
new IfThenElse(Token.NoToken),
new ExprSeq(p, havocTempExpr, v))));
}
- } else if (cmd is CallCmd) {
- Debug.Assert(useProcedurePredicates);
- var cCmd = (CallCmd)cmd;
- cCmd.Ins.Insert(0, p);
- cmdSeq.Add(cCmd);
- }
- else if (cmd is CommentCmd) {
+ } else if (cmd is CommentCmd) {
// skip
- }
- else if (cmd is StateCmd) {
+ } else if (cmd is StateCmd) {
var sCmd = (StateCmd)cmd;
var newCmdSeq = new CmdSeq();
foreach (Cmd c in sCmd.Cmds)
PredicateCmd(p, newCmdSeq, c);
sCmd.Cmds = newCmdSeq;
cmdSeq.Add(sCmd);
- }
- else {
+ } else {
Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString());
}
}
- void PredicateTransferCmd(Expr p, Block src, CmdSeq cmdSeq, TransferCmd cmd) {
+ // hasPredicatedRegion is true iff the block or its targets are predicated
+ // (i.e. we enter, stay within or exit a predicated region).
+ void PredicateTransferCmd(Expr p, Block src, CmdSeq cmdSeq, TransferCmd cmd, out bool hasPredicatedRegion) {
+ hasPredicatedRegion = predMap.ContainsKey(src);
+
if (cmd is GotoCmd) {
var gCmd = (GotoCmd)cmd;
+
+ hasPredicatedRegion = hasPredicatedRegion ||
+ gCmd.labelTargets.Cast<Block>().Any(b => predMap.ContainsKey(b));
+
if (gCmd.labelTargets.Length == 1) {
if (defMap.ContainsKey(gCmd.labelTargets[0]))
PredicateCmd(p, cmdSeq,
@@ -138,8 +151,12 @@ public class SmartBlockPredicator {
Expr.Ident(predMap[gCmd.labelTargets[0]]), Expr.True));
} else {
Debug.Assert(gCmd.labelTargets.Length > 1);
- Debug.Assert(gCmd.labelTargets.Cast<Block>().All(t => partInfo.ContainsKey(t)));
+ Debug.Assert(gCmd.labelTargets.Cast<Block>().All(t => uni.IsUniform(impl.Name, t) ||
+ partInfo.ContainsKey(t)));
foreach (Block target in gCmd.labelTargets) {
+ if (!partInfo.ContainsKey(target))
+ continue;
+
var part = partInfo[target];
if (defMap.ContainsKey(part.realDest))
PredicateCmd(p, cmdSeq,
@@ -191,12 +208,16 @@ public class SmartBlockPredicator {
var ownedPreds = new HashSet<Variable>();
ownedMap[header] = ownedPreds;
- predMap[header] = headPredicate;
- defMap[header] = headPredicate;
- regionPreds.Add(new Tuple<Block, Variable>(header, headPredicate));
+ if (headPredicate != null) {
+ predMap[header] = headPredicate;
+ defMap[header] = headPredicate;
+ regionPreds.Add(new Tuple<Block, Variable>(header, headPredicate));
+ }
while (i.MoveNext()) {
var block = i.Current;
+ if (uni != null && uni.IsUniform(impl.Name, block.Item1))
+ continue;
if (block.Item2) {
if (block.Item1 == header)
return;
@@ -247,7 +268,7 @@ public class SmartBlockPredicator {
ownedMap = new Dictionary<Block, HashSet<Variable>>();
parentMap = new Dictionary<Block, Block>();
AssignPredicates(blockGraph, dom, pdom, iter,
- useProcedurePredicates ? impl.InParams[0] : null,
+ myUseProcedurePredicates ? impl.InParams[0] : null,
ref predCount);
}
@@ -303,6 +324,9 @@ public class SmartBlockPredicator {
Dictionary<Block, PartInfo> BuildPartitionInfo() {
var partInfo = new Dictionary<Block, PartInfo>();
foreach (var block in blockGraph.Nodes) {
+ if (uni.IsUniform(impl.Name, block))
+ continue;
+
var parts = block.Cmds.Cast<Cmd>().TakeWhile(
c => c is AssumeCmd &&
QKeyValue.FindBoolAttribute(((AssumeCmd)c).Attributes, "partition"));
@@ -335,79 +359,103 @@ public class SmartBlockPredicator {
AssignPredicates();
partInfo = BuildPartitionInfo();
- if (useProcedurePredicates)
+ if (myUseProcedurePredicates)
fp = Expr.Ident(impl.InParams[0]);
var newBlocks = new List<Block>();
Block prevBlock = null;
foreach (var n in sortedBlocks) {
- var p = predMap[n.Item1];
- var pExpr = Expr.Ident(p);
-
- if (n.Item2) {
- var backedgeBlock = new Block();
- newBlocks.Add(backedgeBlock);
-
- backedgeBlock.Label = n.Item1.Label + ".backedge";
- backedgeBlock.Cmds = new CmdSeq(new AssumeCmd(Token.NoToken, pExpr,
- new QKeyValue(Token.NoToken, "backedge", new List<object>(), null)));
- backedgeBlock.TransferCmd = new GotoCmd(Token.NoToken,
- new BlockSeq(n.Item1));
-
- var tailBlock = new Block();
- newBlocks.Add(tailBlock);
-
- tailBlock.Label = n.Item1.Label + ".tail";
- tailBlock.Cmds = new CmdSeq(new AssumeCmd(Token.NoToken,
- Expr.Not(pExpr)));
-
- if (prevBlock != null)
- prevBlock.TransferCmd = new GotoCmd(Token.NoToken,
- new BlockSeq(backedgeBlock, tailBlock));
- prevBlock = tailBlock;
- } else {
- var runBlock = n.Item1;
- var oldCmdSeq = runBlock.Cmds;
- runBlock.Cmds = new CmdSeq();
- newBlocks.Add(runBlock);
- if (prevBlock != null)
- prevBlock.TransferCmd = new GotoCmd(Token.NoToken,
- new BlockSeq(runBlock));
-
- if (parentMap.ContainsKey(runBlock)) {
- var parent = parentMap[runBlock];
- if (predMap.ContainsKey(parent)) {
- var parentPred = predMap[parent];
- if (parentPred != null) {
- runBlock.Cmds.Add(new AssertCmd(Token.NoToken,
- Expr.Imp(pExpr, Expr.Ident(parentPred))));
- }
+ if (predMap.ContainsKey(n.Item1)) {
+ var p = predMap[n.Item1];
+ var pExpr = Expr.Ident(p);
+
+ if (n.Item2) {
+ var backedgeBlock = new Block();
+ newBlocks.Add(backedgeBlock);
+
+ backedgeBlock.Label = n.Item1.Label + ".backedge";
+ backedgeBlock.Cmds = new CmdSeq(new AssumeCmd(Token.NoToken, pExpr,
+ new QKeyValue(Token.NoToken, "backedge", new List<object>(), null)));
+ backedgeBlock.TransferCmd = new GotoCmd(Token.NoToken,
+ new BlockSeq(n.Item1));
+
+ var tailBlock = new Block();
+ newBlocks.Add(tailBlock);
+
+ tailBlock.Label = n.Item1.Label + ".tail";
+ tailBlock.Cmds = new CmdSeq(new AssumeCmd(Token.NoToken,
+ Expr.Not(pExpr)));
+
+ if (uni != null && !uni.IsUniform(impl.Name, n.Item1)) {
+ uni.AddNonUniform(impl.Name, backedgeBlock);
+ uni.AddNonUniform(impl.Name, tailBlock);
}
+
+ if (prevBlock != null)
+ prevBlock.TransferCmd = new GotoCmd(Token.NoToken,
+ new BlockSeq(backedgeBlock, tailBlock));
+ prevBlock = tailBlock;
+ } else {
+ PredicateBlock(pExpr, n.Item1, newBlocks, ref prevBlock);
}
+ } else {
+ if (!n.Item2) {
+ PredicateBlock(null, n.Item1, newBlocks, ref prevBlock);
+ }
+ }
+ }
- var transferCmd = runBlock.TransferCmd;
- foreach (Cmd cmd in oldCmdSeq)
- PredicateCmd(pExpr, newBlocks, runBlock, cmd, out runBlock);
+ if (prevBlock != null)
+ prevBlock.TransferCmd = new ReturnCmd(Token.NoToken);
- if (ownedMap.ContainsKey(n.Item1)) {
- var owned = ownedMap[n.Item1];
- foreach (var v in owned)
- runBlock.Cmds.Add(Cmd.SimpleAssign(Token.NoToken, Expr.Ident(v), Expr.False));
- }
+ impl.Blocks = newBlocks;
+ }
+
+ private void PredicateBlock(Expr pExpr, Block block, List<Block> newBlocks, ref Block prevBlock) {
+ var firstBlock = block;
- PredicateTransferCmd(pExpr, runBlock, runBlock.Cmds, transferCmd);
+ var oldCmdSeq = block.Cmds;
+ block.Cmds = new CmdSeq();
+ newBlocks.Add(block);
+ if (prevBlock != null) {
+ prevBlock.TransferCmd = new GotoCmd(Token.NoToken, new BlockSeq(block));
+ }
- prevBlock = runBlock;
- doneBlocks.Add(runBlock);
+ if (parentMap.ContainsKey(block)) {
+ var parent = parentMap[block];
+ if (predMap.ContainsKey(parent)) {
+ var parentPred = predMap[parent];
+ if (parentPred != null) {
+ block.Cmds.Add(new AssertCmd(Token.NoToken,
+ pExpr != null ? (Expr)Expr.Imp(pExpr, Expr.Ident(parentPred))
+ : Expr.Ident(parentPred)));
+ }
}
}
- prevBlock.TransferCmd = new ReturnCmd(Token.NoToken);
- impl.Blocks = newBlocks;
+ var transferCmd = block.TransferCmd;
+ foreach (Cmd cmd in oldCmdSeq)
+ PredicateCmd(pExpr, newBlocks, block, cmd, out block);
+
+ if (ownedMap.ContainsKey(firstBlock)) {
+ var owned = ownedMap[firstBlock];
+ foreach (var v in owned)
+ block.Cmds.Add(Cmd.SimpleAssign(Token.NoToken, Expr.Ident(v), Expr.False));
+ }
+
+ bool hasPredicatedRegion;
+ PredicateTransferCmd(pExpr, block, block.Cmds, transferCmd, out hasPredicatedRegion);
+
+ if (hasPredicatedRegion)
+ prevBlock = block;
+ else
+ prevBlock = null;
+
+ doneBlocks.Add(block);
}
private Expr CreateIfFPThenElse(Expr then, Expr eElse) {
- if (useProcedurePredicates) {
+ if (myUseProcedurePredicates) {
return new NAryExpr(Token.NoToken,
new IfThenElse(Token.NoToken),
new ExprSeq(fp, then, eElse));
@@ -417,49 +465,60 @@ public class SmartBlockPredicator {
}
public static void Predicate(Program p,
- bool useProcedurePredicates = true) {
+ Func<Procedure, bool> useProcedurePredicates = null,
+ UniformityAnalyser uni = null) {
+ useProcedurePredicates = useProcedurePredicates ?? (proc => false);
+ if (uni != null) {
+ var oldUPP = useProcedurePredicates;
+ useProcedurePredicates = proc => oldUPP(proc) && !uni.IsUniform(proc.Name);
+ }
+
foreach (var decl in p.TopLevelDeclarations.ToList()) {
- if (useProcedurePredicates && decl is DeclWithFormals && !(decl is Function)) {
- var dwf = (DeclWithFormals)decl;
- var fpVar = new Formal(Token.NoToken,
- new TypedIdent(Token.NoToken, "_P",
- Microsoft.Boogie.Type.Bool),
- /*incoming=*/true);
- dwf.InParams = new VariableSeq(
- (new Variable[] {fpVar}.Concat(dwf.InParams.Cast<Variable>()))
- .ToArray());
-
- if (dwf is Procedure)
- {
- var proc = (Procedure)dwf;
+ if (decl is Procedure || decl is Implementation) {
+ var proc = decl as Procedure;
+ Implementation impl = null;
+ if (proc == null) {
+ impl = (Implementation)decl;
+ proc = impl.Proc;
+ }
+
+ bool upp = useProcedurePredicates(proc);
+ if (upp) {
+ var dwf = (DeclWithFormals)decl;
+ var fpVar = new Formal(Token.NoToken,
+ new TypedIdent(Token.NoToken, "_P",
+ Microsoft.Boogie.Type.Bool),
+ /*incoming=*/true);
+ dwf.InParams = new VariableSeq(
+ (new Variable[] {fpVar}.Concat(dwf.InParams.Cast<Variable>()))
+ .ToArray());
+
+ if (impl == null) {
var newRequires = new RequiresSeq();
- foreach (Requires r in proc.Requires)
- {
- newRequires.Add(new Requires(r.Free,
- new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar)).VisitExpr(r.Condition)));
+ foreach (Requires r in proc.Requires) {
+ newRequires.Add(new Requires(r.Free,
+ new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar)).VisitExpr(r.Condition)));
}
var newEnsures = new EnsuresSeq();
- foreach (Ensures e in proc.Ensures)
- {
- newEnsures.Add(new Ensures(e.Free,
- new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar)).VisitExpr(e.Condition)));
+ foreach (Ensures e in proc.Ensures) {
+ newEnsures.Add(new Ensures(e.Free,
+ new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar)).VisitExpr(e.Condition)));
}
+ }
}
+ if (impl != null) {
+ try {
+ new SmartBlockPredicator(p, impl, useProcedurePredicates, uni).PredicateImplementation();
+ } catch (Program.IrreducibleLoopException) { }
+ }
}
-
- try {
- var impl = decl as Implementation;
- if (impl != null)
- new SmartBlockPredicator(p, impl, useProcedurePredicates).PredicateImplementation();
- }
- catch (Program.IrreducibleLoopException) { }
}
}
public static void Predicate(Program p, Implementation impl) {
try {
- new SmartBlockPredicator(p, impl, false).PredicateImplementation();
+ new SmartBlockPredicator(p, impl, proc => false, null).PredicateImplementation();
}
catch (Program.IrreducibleLoopException) { }
}
diff --git a/Source/Predication/UniformityAnalyser.cs b/Source/Predication/UniformityAnalyser.cs
new file mode 100644
index 00000000..3408d88b
--- /dev/null
+++ b/Source/Predication/UniformityAnalyser.cs
@@ -0,0 +1,591 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Diagnostics;
+using Microsoft.Boogie.GraphUtil;
+
+namespace Microsoft.Boogie
+{
+
+ public class UniformityAnalyser
+ {
+ private Program prog;
+
+ private bool doAnalysis, unstructured;
+
+ private ISet<Implementation> entryPoints;
+
+ private IEnumerable<Variable> nonUniformVars;
+
+ private bool ProcedureChanged;
+
+ private Dictionary<string, KeyValuePair<bool, Dictionary<string, bool>>> uniformityInfo;
+
+ private Dictionary<string, HashSet<int>> nonUniformLoops;
+
+ private Dictionary<string, HashSet<Block>> nonUniformBlocks;
+
+ private Dictionary<string, HashSet<int>> loopsWithNonuniformReturn;
+
+ private Dictionary<string, List<string>> inParameters;
+
+ private Dictionary<string, List<string>> outParameters;
+
+ private List<WhileCmd> loopStack;
+
+ private bool hitNonuniformReturn;
+
+ /// <summary>
+ /// Simplifies the CFG of the given implementation impl by merging each
+ /// basic block with a single predecessor into that predecessor if the
+ /// predecessor has a single successor. If a uniformity analyser is
+ /// being used then block will only be merged if they are both uniform
+ /// or both non-uniform
+ /// </summary>
+ public static void MergeBlocksIntoPredecessors(Program prog, Implementation impl, UniformityAnalyser uni)
+ {
+ var blockGraph = prog.ProcessLoops(impl);
+ var predMap = new Dictionary<Block, Block>();
+ foreach (var block in blockGraph.Nodes)
+ {
+ try
+ {
+ var pred = blockGraph.Predecessors(block).Single();
+ if (blockGraph.Successors(pred).Single() == block &&
+ (uni == null ||
+ (uni.IsUniform(impl.Name, pred) && uni.IsUniform(impl.Name, block)) ||
+ (!uni.IsUniform(impl.Name, pred) && !uni.IsUniform(impl.Name, block))))
+ {
+ Block predMapping;
+ while (predMap.TryGetValue(pred, out predMapping))
+ pred = predMapping;
+ pred.Cmds.AddRange(block.Cmds);
+ pred.TransferCmd = block.TransferCmd;
+ impl.Blocks.Remove(block);
+ predMap[block] = pred;
+ }
+ // If Single throws an exception above (i.e. not exactly one pred/succ), skip this block.
+ }
+ catch (InvalidOperationException) { }
+ }
+ }
+
+ public UniformityAnalyser(Program prog, bool doAnalysis, bool unstructured, ISet<Implementation> entryPoints, IEnumerable<Variable> nonUniformVars)
+ {
+ this.prog = prog;
+ this.doAnalysis = doAnalysis;
+ this.unstructured = unstructured;
+ this.entryPoints = entryPoints;
+ this.nonUniformVars = nonUniformVars;
+ uniformityInfo = new Dictionary<string, KeyValuePair<bool, Dictionary<string, bool>>>();
+ nonUniformLoops = new Dictionary<string, HashSet<int>>();
+ nonUniformBlocks = new Dictionary<string, HashSet<Block>>();
+ loopsWithNonuniformReturn = new Dictionary<string, HashSet<int>>();
+ inParameters = new Dictionary<string, List<string>>();
+ outParameters = new Dictionary<string, List<string>>();
+ loopStack = new List<WhileCmd>();
+ }
+
+ public void Analyse()
+ {
+ var impls = prog.TopLevelDeclarations.OfType<Implementation>();
+
+ foreach (var Impl in impls)
+ {
+ bool uniformProcedure = doAnalysis || entryPoints.Contains(Impl);
+
+ uniformityInfo.Add(Impl.Name, new KeyValuePair<bool, Dictionary<string, bool>>
+ (uniformProcedure, new Dictionary<string, bool> ()));
+
+ nonUniformLoops.Add(Impl.Name, new HashSet<int>());
+ loopsWithNonuniformReturn.Add(Impl.Name, new HashSet<int>());
+
+ foreach (var v in nonUniformVars)
+ SetNonUniform(Impl.Name, v.Name);
+
+ foreach (Variable v in Impl.LocVars)
+ {
+ if (doAnalysis)
+ {
+ SetUniform(Impl.Name, v.Name);
+ }
+ else
+ {
+ SetNonUniform(Impl.Name, v.Name);
+ }
+ }
+
+ inParameters[Impl.Name] = new List<string>();
+
+ foreach (Variable v in Impl.InParams)
+ {
+ inParameters[Impl.Name].Add(v.Name);
+ if (doAnalysis)
+ {
+ SetUniform(Impl.Name, v.Name);
+ }
+ else
+ {
+ SetNonUniform(Impl.Name, v.Name);
+ }
+ }
+
+ outParameters[Impl.Name] = new List<string>();
+ foreach (Variable v in Impl.OutParams)
+ {
+ outParameters[Impl.Name].Add(v.Name);
+ if (doAnalysis)
+ {
+ SetUniform(Impl.Name, v.Name);
+ }
+ else
+ {
+ SetNonUniform(Impl.Name, v.Name);
+ }
+ }
+
+ ProcedureChanged = true;
+ }
+
+ if (doAnalysis)
+ {
+ while (ProcedureChanged)
+ {
+ ProcedureChanged = false;
+
+ foreach (var Impl in impls)
+ {
+ hitNonuniformReturn = false;
+ Analyse(Impl, uniformityInfo[Impl.Name].Key);
+ }
+ }
+ }
+
+ foreach (var Impl in impls)
+ {
+ if (!IsUniform (Impl.Name))
+ {
+ List<string> newIns = new List<String>();
+ newIns.Add("_P");
+ foreach (string s in inParameters[Impl.Name])
+ {
+ newIns.Add(s);
+ }
+ inParameters[Impl.Name] = newIns;
+ }
+ }
+ }
+
+ private void Analyse(Implementation Impl, bool ControlFlowIsUniform)
+ {
+ if (unstructured)
+ {
+ if (!ControlFlowIsUniform)
+ {
+ nonUniformBlocks[Impl.Name] = new HashSet<Block>(Impl.Blocks);
+
+ foreach (Variable v in Impl.LocVars) {
+ if (IsUniform(Impl.Name, v.Name)) {
+ SetNonUniform(Impl.Name, v.Name);
+ }
+ }
+
+ foreach (Variable v in Impl.InParams) {
+ if (IsUniform(Impl.Name, v.Name)) {
+ SetNonUniform(Impl.Name, v.Name);
+ }
+ }
+
+ foreach (Variable v in Impl.OutParams) {
+ if (IsUniform(Impl.Name, v.Name)) {
+ SetNonUniform(Impl.Name, v.Name);
+ }
+ }
+
+ return;
+ }
+
+ Graph<Block> blockGraph = prog.ProcessLoops(Impl);
+ var ctrlDep = blockGraph.ControlDependence();
+
+ // Compute transitive closure of control dependence info.
+ bool changed;
+ do
+ {
+ changed = false;
+ foreach (var depEntry in ctrlDep)
+ {
+ var newDepSet = new HashSet<Block>(depEntry.Value);
+ foreach (var dep in depEntry.Value)
+ {
+ if (ctrlDep.ContainsKey(dep))
+ newDepSet.UnionWith(ctrlDep[dep]);
+ }
+ if (newDepSet.Count != depEntry.Value.Count)
+ {
+ depEntry.Value.UnionWith(newDepSet);
+ changed = true;
+ }
+ }
+ } while (changed);
+
+ var nonUniformBlockSet = new HashSet<Block>();
+ nonUniformBlocks[Impl.Name] = nonUniformBlockSet;
+
+ do {
+ changed = false;
+ foreach (var block in Impl.Blocks) {
+ bool uniform = !nonUniformBlockSet.Contains(block);
+ bool newUniform = Analyse(Impl, block.Cmds, uniform);
+ if (uniform && !newUniform) {
+ changed = true;
+ nonUniformBlockSet.Add(block);
+ Block pred = blockGraph.Predecessors(block).Single();
+ if (ctrlDep.ContainsKey(pred))
+ nonUniformBlockSet.UnionWith(ctrlDep[pred]);
+ }
+ }
+ } while (changed);
+ }
+ else
+ {
+ Analyse(Impl, Impl.StructuredStmts, ControlFlowIsUniform);
+ }
+ }
+
+
+ private void Analyse(Implementation impl, StmtList stmtList, bool ControlFlowIsUniform)
+ {
+ ControlFlowIsUniform &= !hitNonuniformReturn;
+ foreach (BigBlock bb in stmtList.BigBlocks)
+ {
+ Analyse(impl, bb, ControlFlowIsUniform);
+ }
+ }
+
+ private Implementation GetImplementation(string procedureName)
+ {
+ foreach (Declaration D in prog.TopLevelDeclarations)
+ {
+ if (D is Implementation && ((D as Implementation).Name == procedureName))
+ {
+ return D as Implementation;
+ }
+ }
+ return null;
+ }
+
+ private void Analyse(Implementation impl, BigBlock bb, bool ControlFlowIsUniform)
+ {
+ ControlFlowIsUniform &= !hitNonuniformReturn;
+ Analyse(impl, bb.simpleCmds, ControlFlowIsUniform);
+
+ if (bb.ec is WhileCmd)
+ {
+ WhileCmd wc = bb.ec as WhileCmd;
+ loopStack.Add(wc);
+ Analyse(impl, wc.Body, ControlFlowIsUniform && IsUniform(impl.Name, wc.Guard) &&
+ !nonUniformLoops[impl.Name].Contains(GetLoopId(wc)));
+ loopStack.RemoveAt(loopStack.Count - 1);
+ }
+ else if (bb.ec is IfCmd)
+ {
+ IfCmd ifCmd = bb.ec as IfCmd;
+ Analyse(impl, ifCmd.thn, ControlFlowIsUniform && IsUniform(impl.Name, ifCmd.Guard));
+ if (ifCmd.elseBlock != null)
+ {
+ Analyse(impl, ifCmd.elseBlock, ControlFlowIsUniform && IsUniform(impl.Name, ifCmd.Guard));
+ }
+ Debug.Assert(ifCmd.elseIf == null);
+ }
+ else if (bb.ec is BreakCmd)
+ {
+ if (!ControlFlowIsUniform && !nonUniformLoops[impl.Name].Contains(GetLoopId(loopStack[loopStack.Count - 1])))
+ {
+ SetNonUniform(impl.Name, loopStack[loopStack.Count - 1]);
+ }
+ }
+
+ if (bb.tc is ReturnCmd && !ControlFlowIsUniform)
+ {
+ hitNonuniformReturn = true;
+ if (loopStack.Count > 0 && !nonUniformLoops[impl.Name].Contains(GetLoopId(loopStack[0])))
+ {
+ SetNonUniform(impl.Name, loopStack[0]);
+ loopsWithNonuniformReturn[impl.Name].Add(GetLoopId(loopStack[0]));
+ }
+ }
+
+
+ }
+
+ private bool Analyse(Implementation impl, CmdSeq cmdSeq, bool ControlFlowIsUniform)
+ {
+ foreach (Cmd c in cmdSeq)
+ {
+ if (c is AssignCmd)
+ {
+ AssignCmd assignCmd = c as AssignCmd;
+ foreach (var a in assignCmd.Lhss.Zip(assignCmd.Rhss))
+ {
+
+ if (a.Item1 is SimpleAssignLhs)
+ {
+ SimpleAssignLhs lhs = a.Item1 as SimpleAssignLhs;
+ Expr rhs = a.Item2;
+ if (IsUniform(impl.Name, lhs.AssignedVariable.Name) &&
+ (!ControlFlowIsUniform || !IsUniform(impl.Name, rhs)))
+ {
+ SetNonUniform(impl.Name, lhs.AssignedVariable.Name);
+ }
+
+ }
+ }
+ }
+ else if (c is HavocCmd)
+ {
+ HavocCmd havocCmd = c as HavocCmd;
+ foreach(IdentifierExpr ie in havocCmd.Vars)
+ {
+ if(IsUniform(impl.Name, ie.Decl.Name)) {
+ SetNonUniform(impl.Name, ie.Decl.Name);
+ }
+ }
+ }
+ else if (c is CallCmd)
+ {
+ CallCmd callCmd = c as CallCmd;
+ Implementation CalleeImplementation = GetImplementation(callCmd.callee);
+
+ if (CalleeImplementation != null)
+ {
+
+ if (!ControlFlowIsUniform)
+ {
+ if (IsUniform(callCmd.callee))
+ {
+ SetNonUniform(callCmd.callee);
+ }
+ }
+ for (int i = 0; i < CalleeImplementation.InParams.Length; i++)
+ {
+ if (IsUniform(callCmd.callee, CalleeImplementation.InParams[i].Name)
+ && !IsUniform(impl.Name, callCmd.Ins[i]))
+ {
+ SetNonUniform(callCmd.callee, CalleeImplementation.InParams[i].Name);
+ }
+ }
+
+ for (int i = 0; i < CalleeImplementation.OutParams.Length; i++)
+ {
+ if (IsUniform(impl.Name, callCmd.Outs[i].Name)
+ && !IsUniform(callCmd.callee, CalleeImplementation.OutParams[i].Name))
+ {
+ SetNonUniform(impl.Name, callCmd.Outs[i].Name);
+ }
+ }
+
+ }
+ }
+ else if (c is AssumeCmd)
+ {
+ var ac = (AssumeCmd)c;
+ if (ControlFlowIsUniform && QKeyValue.FindBoolAttribute(ac.Attributes, "partition") &&
+ !IsUniform(impl.Name, ac.Expr))
+ {
+ ControlFlowIsUniform = false;
+ }
+ }
+ }
+
+ return ControlFlowIsUniform;
+ }
+
+ private int GetLoopId(WhileCmd wc)
+ {
+ AssertCmd inv = wc.Invariants[0] as AssertCmd;
+ Debug.Assert(inv.Attributes.Key.Contains("loophead_"));
+ return Convert.ToInt32(inv.Attributes.Key.Substring("loophead_".Length));
+ }
+
+ private void SetNonUniform(string procedureName)
+ {
+ uniformityInfo[procedureName] = new KeyValuePair<bool,Dictionary<string,bool>>
+ (false, uniformityInfo[procedureName].Value);
+ RecordProcedureChanged();
+ }
+
+ private void SetNonUniform(string procedureName, WhileCmd wc)
+ {
+ nonUniformLoops[procedureName].Add(GetLoopId(wc));
+ RecordProcedureChanged();
+ }
+
+ public bool IsUniform(string procedureName)
+ {
+ if (!uniformityInfo.ContainsKey(procedureName))
+ {
+ return false;
+ }
+ return uniformityInfo[procedureName].Key;
+ }
+
+ public bool IsUniform(string procedureName, Block b)
+ {
+ if (!nonUniformBlocks.ContainsKey(procedureName))
+ {
+ return false;
+ }
+ return !nonUniformBlocks[procedureName].Contains(b);
+ }
+
+ class UniformExpressionAnalysisVisitor : StandardVisitor {
+
+ private bool isUniform = true;
+ private Dictionary<string, bool> uniformityInfo;
+
+ public UniformExpressionAnalysisVisitor(Dictionary<string, bool> uniformityInfo) {
+ this.uniformityInfo = uniformityInfo;
+ }
+
+ public override Variable VisitVariable(Variable v) {
+ if (!uniformityInfo.ContainsKey(v.Name)) {
+ isUniform = isUniform && (v is Constant);
+ } else if (!uniformityInfo[v.Name]) {
+ isUniform = false;
+ }
+
+ return v;
+ }
+
+ internal bool IsUniform() {
+ return isUniform;
+ }
+ }
+
+ public bool IsUniform(string procedureName, Expr expr)
+ {
+ UniformExpressionAnalysisVisitor visitor = new UniformExpressionAnalysisVisitor(uniformityInfo[procedureName].Value);
+ visitor.VisitExpr(expr);
+ return visitor.IsUniform();
+ }
+
+ public bool IsUniform(string procedureName, string v)
+ {
+ if (!uniformityInfo.ContainsKey(procedureName))
+ {
+ return false;
+ }
+
+ if (!uniformityInfo[procedureName].Value.ContainsKey(v))
+ {
+ return false;
+ }
+ return uniformityInfo[procedureName].Value[v];
+ }
+
+ private void SetUniform(string procedureName, string v)
+ {
+ uniformityInfo[procedureName].Value[v] = true;
+ RecordProcedureChanged();
+ }
+
+ private void RecordProcedureChanged()
+ {
+ ProcedureChanged = true;
+ }
+
+ private void SetNonUniform(string procedureName, string v)
+ {
+ uniformityInfo[procedureName].Value[v] = false;
+ RecordProcedureChanged();
+ }
+
+ public void dump()
+ {
+ foreach (string p in uniformityInfo.Keys)
+ {
+ Console.WriteLine("Procedure " + p + ": "
+ + (uniformityInfo[p].Key ? "uniform" : "nonuniform"));
+ foreach (string v in uniformityInfo[p].Value.Keys)
+ {
+ Console.WriteLine(" " + v + ": " +
+ (uniformityInfo[p].Value[v] ? "uniform" : "nonuniform"));
+ }
+ Console.Write("Ins [");
+ for (int i = 0; i < inParameters[p].Count; i++)
+ {
+ Console.Write((i == 0 ? "" : ", ") + inParameters[p][i]);
+ }
+ Console.WriteLine("]");
+ Console.Write("Outs [");
+ for (int i = 0; i < outParameters[p].Count; i++)
+ {
+ Console.Write((i == 0 ? "" : ", ") + outParameters[p][i]);
+ }
+ Console.WriteLine("]");
+ Console.Write("Non-uniform loops:");
+ foreach (int l in nonUniformLoops[p])
+ {
+ Console.Write(" " + l);
+ }
+ Console.WriteLine();
+ Console.Write("Non-uniform blocks:");
+ foreach (Block b in nonUniformBlocks[p])
+ {
+ Console.Write(" " + b.Label);
+ }
+ Console.WriteLine();
+ }
+ }
+
+
+ public string GetInParameter(string procName, int i)
+ {
+ return inParameters[procName][i];
+ }
+
+ public string GetOutParameter(string procName, int i)
+ {
+ return outParameters[procName][i];
+ }
+
+
+ public bool knowsOf(string p)
+ {
+ return uniformityInfo.ContainsKey(p);
+ }
+
+ public void AddNonUniform(string proc, string v)
+ {
+ if (uniformityInfo.ContainsKey(proc))
+ {
+ Debug.Assert(!uniformityInfo[proc].Value.ContainsKey(v));
+ uniformityInfo[proc].Value[v] = false;
+ }
+ }
+
+ public void AddNonUniform(string proc, Block b) {
+ if (nonUniformBlocks.ContainsKey(proc)) {
+ Debug.Assert(!nonUniformBlocks[proc].Contains(b));
+ nonUniformBlocks[proc].Add(b);
+ }
+ }
+
+ public bool IsUniform(string proc, WhileCmd wc)
+ {
+ if (unstructured)
+ return false;
+
+ return !nonUniformLoops[proc].Contains(GetLoopId(wc));
+ }
+
+ public bool HasNonuniformReturn(string proc, WhileCmd whileCmd)
+ {
+ return loopsWithNonuniformReturn[proc].Contains(GetLoopId(whileCmd));
+ }
+ }
+
+}
diff --git a/Source/Provers/Isabelle/Isabelle.csproj b/Source/Provers/Isabelle/Isabelle.csproj
deleted file mode 100644
index 0593ee45..00000000
--- a/Source/Provers/Isabelle/Isabelle.csproj
+++ /dev/null
@@ -1,210 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{435D5BD0-6F62-49F8-BB24-33E2257519AD}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Microsoft.Boogie.Isabelle</RootNamespace>
- <AssemblyName>Provers.Isabelle</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile>Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for Isabelle.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\Provers.Isabelle.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Prover.cs" />
- <Compile Include="..\..\version.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCExpr\VCExpr.csproj">
- <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
- <Name>VCExpr</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project> \ No newline at end of file
diff --git a/Source/Provers/Isabelle/Prover.cs b/Source/Provers/Isabelle/Prover.cs
deleted file mode 100644
index 35913019..00000000
--- a/Source/Provers/Isabelle/Prover.cs
+++ /dev/null
@@ -1,1083 +0,0 @@
-/*
-Copyright (c) 2009, Sascha Boehme, Technische Universitaet Muenchen
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-* Neither the name of the Technische Universitaet Muenchen nor the names of
- its contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-using System;
-using System.IO;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.Isabelle {
- public class IsabelleProverOptions : ProverOptions {
- private string filename = null;
- public string Filename = "";
-
- public bool AllTypes = false;
-
- protected override bool Parse(string opt) {
- //Contract.Requires(opt != null);
- bool v2 = false;
- return
- ParseString(opt, "ISABELLE_INPUT", ref filename) ||
- ParseBool(opt, "ISABELLE_FULL", ref AllTypes) ||
- ParseBool(opt, "V2", ref v2) ||
- base.Parse(opt);
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Filename != null);
- }
-
-
-
- public override void PostParse() {
- base.PostParse();
-
- if (filename == null) {
- ReportError("Missing ISABELLE_INPUT option. " +
- "This option expects a filename (with extension .b2i).");
- } else if (!Path.GetExtension(filename).Equals(".b2i")) {
- filename = Path.ChangeExtension(filename, ".b2i");
- }
- Filename = cce.NonNull(filename);
- }
- }
-
- public class Factory : ProverFactory {
- private static int index = 0;
-
- public override ProverOptions BlankProverOptions() {
- Contract.Ensures(Contract.Result<ProverOptions>() != null);//POSTCORE
-
- return new IsabelleProverOptions();
- }
-
- public override object NewProverContext(ProverOptions options) {
- //Contract.Requires(options != null);
- Contract.Ensures(Contract.Result<object>() != null);//POSTCORE
-
- IsabelleProverOptions opts = (IsabelleProverOptions)options;
- string filename = opts.Filename;
- Contract.Assert(filename != null);
- lock (this) {
- if (index > 0) {
- filename = Path.ChangeExtension(filename, "." + index + ".b2i");
- }
- index++;
- if (File.Exists(filename)) {
- File.Delete(filename);
- }
- }
- return new IsabelleContext(filename, opts.AllTypes);
- }
-
- public override object SpawnProver(ProverOptions options, object ctxt) {
- //Contract.Requires(options != null);
- //Contract.Requires(ctxt != null);
- Contract.Ensures(Contract.Result<object>() != null);//POSTCORE
-
- return new IsabelleInterface(cce.NonNull((ProverContext)ctxt));
- }
-
- // we prefer DAG outputs over LET
- public override bool SupportsDags {
- get {
- return true;
- }
- }
-
- // this works well in Isabelle, but we do not get structural information
- public override CommandLineOptions.VCVariety DefaultVCVariety {
- get {
- return CommandLineOptions.VCVariety.Dag;
- }
- }
- }
-
- public class IsabelleInterface : ProverInterface {
- private static Dictionary<string/*!*/, int> lastVCIndex =
- new Dictionary<string/*!*/, int>();
-
- private IsabelleContext ctxt;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(lastVCIndex.Keys));
- Contract.Invariant(ctxt != null);
- Contract.Invariant(lastVCIndex != null);
- }
-
-
- public IsabelleInterface(ProverContext ctxt) {
- Contract.Requires(ctxt != null);
- this.ctxt = (IsabelleContext)cce.NonNull(ctxt);
- }
- public override ProverContext Context {
- get {
- Contract.Ensures(Contract.Result<ProverContext>() != null);//POSTCORE
- return ctxt;
- }
- }
- public override VCExpressionGenerator VCExprGen {
- get {
- Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);//POSTCORE
- return cce.NonNull(ctxt.ExprGen);
- }
- }
-
- public override void BeginCheck(string name, VCExpr vc, ErrorHandler h) {
- //Contract.Requires(h != null);
- //Contract.Requires(vc != null);
- //Contract.Requires(name != null);
-
- int index;
- lock (lastVCIndex) {
- lastVCIndex.TryGetValue(name, out index);
- index++;
- lastVCIndex[name] = index;
- }
- lock (ctxt) {
- ctxt.AddVC(name + " " + index, vc, h);
- }
- }
- public override Outcome CheckOutcome(ErrorHandler handler) {
- //Contract.Requires(handler != null);
- return Outcome.Undetermined; // we will check the goal later in Isabelle
- }
- }
-
- public class IsabelleContext : DeclFreeProverContext {
- private List<string/*!*/> declaredFunctions = new List<string/*!*/>();
-
- public readonly string OutputFilename;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(declaredFunctions != null);
- Contract.Invariant(OutputFilename != null);
- Contract.Invariant(cce.NonNullElements(declaredFunctions));
- }
-
- public bool IsFunctionDeclared(string name) {
- Contract.Requires(name != null);
- return declaredFunctions.Contains(name);
- }
- public readonly bool AllTypes;
-
- public IsabelleContext(string outputFilename, bool allTypes)
- : base(new VCExpressionGenerator(), new VCGenerationOptions(new List<string/*!*/> { "isabelle", "external" })) {
- Contract.Requires(outputFilename != null);
-
- this.OutputFilename = outputFilename;
- this.AllTypes = allTypes;
- }
-
- public override object Clone() {
- Contract.Ensures(Contract.Result<object>() != null);//POSTCORE
- return this;
- }
-
- public override void DeclareType(TypeCtorDecl t, string atts) {
- //Contract.Requires(t != null);
-
- B2I b2i = new B2I(this);
- b2i.Write(B2I.Kind.TypeDecl, t.Name + " " + t.Arity + " " +
- B2I.CountOf(t.Attributes));
- b2i.Indent(2);
- b2i.Write(t.Attributes, BoogieExprTranslator);
- b2i.Close();
- }
-
- public override void DeclareConstant(Constant c, bool uniq, string atts) {
- //Contract.Requires(c != null);
- QKeyValue attributes = c.Attributes;
- if (c.Unique) {
- attributes = B2I.Add("unique", null, attributes);
- }
- declaredFunctions.Add(c.Name);
-
- B2I b2i = new B2I(this);
- if (AllTypes) {
- b2i.Write(B2I.Kind.FunDecl, c.Name + " 0 1 " +
- B2I.CountOf(attributes));
- } else {
- b2i.Write(B2I.Kind.FunDecl, c.Name + " 1 " + B2I.CountOf(attributes));
- }
- b2i.Indent(4);
- b2i.Write(c.TypedIdent.Type);
- b2i.Unindent();
- b2i.Indent(2);
- b2i.Write(attributes, BoogieExprTranslator);
- b2i.Close();
- }
-
- public override void DeclareFunction(Function f, string atts) {
- //Contract.Requires(f != null);
- declaredFunctions.Add(f.Name);
-
- B2I b2i = new B2I(this);
- if (AllTypes) {
- b2i.Write(B2I.Kind.FunDecl, f.Name + " " + f.TypeParameters.Length +
- " " + (f.InParams.Length + 1) + " " + B2I.CountOf(f.Attributes));
- b2i.Indent(4);
- foreach (TypeVariable v in f.TypeParameters) {
- Contract.Assert(v != null);
- b2i.Write(v);
- }
- b2i.Unindent();
- } else {
- b2i.Write(B2I.Kind.FunDecl, f.Name + " " + (f.InParams.Length + 1) +
- " " + B2I.CountOf(f.Attributes));
- }
- b2i.Indent(4);
- foreach (Variable v in f.InParams) {
- Contract.Assert(v != null);
- b2i.Write(v.TypedIdent.Type);
- }
- Contract.Assert(f.OutParams.Length == 1);
- b2i.Write(cce.NonNull(f.OutParams[0]).TypedIdent.Type);
- b2i.Unindent();
- b2i.Indent(2);
- b2i.Write(f.Attributes, BoogieExprTranslator);
- b2i.Close();
- }
-
- public override void AddAxiom(Axiom a, string atts) {
- //Contract.Requires(a != null);
- B2I b2i = new B2I(this);
- b2i.Write(B2I.Kind.Axiom, B2I.CountOf(a.Attributes).ToString());
- b2i.Indent(4);
- b2i.Write(BoogieExprTranslator.Translate(a.Expr));
- b2i.Unindent();
- b2i.Indent(2);
- b2i.Write(a.Attributes, BoogieExprTranslator);
- b2i.Close();
- }
-
- public override void AddAxiom(VCExpr e) {
- //Contract.Requires(e != null);
- B2I b2i = new B2I(this);
- b2i.Write(B2I.Kind.Axiom, "0");
- b2i.Indent(4);
- b2i.Write(e);
- b2i.Close();
- }
-
- public override void DeclareGlobalVariable(GlobalVariable v, string atts) {
- //Contract.Requires(v != null);
- B2I b2i = new B2I(this);
- b2i.Write(B2I.Kind.VarDecl, v.Name + " " + B2I.CountOf(v.Attributes));
- b2i.Indent(4);
- b2i.Write(v.TypedIdent.Type);
- b2i.Unindent();
- b2i.Indent(2);
- b2i.Write(v.Attributes, BoogieExprTranslator);
- b2i.Close();
- }
-
- public void AddVC(string name, VCExpr vc,
- ProverInterface.ErrorHandler h) {
- Contract.Requires(name != null);
- Contract.Requires(vc != null);
- Contract.Requires(h != null);
- B2I b2i = new B2I(this);
- b2i.Write(B2I.Kind.VC, name);
- b2i.Indent(4);
- b2i.Write(vc, h);
- b2i.Close();
- }
- }
-
- class B2I {
-
- private TextWriter w;
- private VCExprWriter exprWriter = new VCExprWriter();
- private VCExprOpWriter exprOpWriter = new VCExprOpWriter();
- private ProverInterface.ErrorHandler eh = null;
- public ProverInterface.ErrorHandler LabelRenamer {
- get {
- return eh;
- }
- }
- public readonly IsabelleContext Context;
- private Stack<int> indents;
- private static int[] default_indent = new int[] { 0 };
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(w != null);
- Contract.Invariant(exprWriter != null);
- Contract.Invariant(exprOpWriter != null);
- Contract.Invariant(Context != null);
- Contract.Invariant(indents != null);
- }
-
-
- public B2I(IsabelleContext ctxt) {
- Contract.Requires(ctxt != null);
- Context = ctxt;
- w = new StreamWriter(ctxt.OutputFilename, true);
- indents = new Stack<int>(default_indent);
- }
- public void Close() {
- w.Close();
- }
-
- public void Indent(int indent) {
- indents.Push(indent + indents.Peek());
- }
- public void Unindent() {
- indents.Pop();
- }
-
- private void DoWrite(Kind k, string s) {
- Contract.Requires(s != null);
- w.WriteLine(new String(' ', indents.Peek()) + StringOfKind(k) + s);
- }
- public void Write(Kind k) {
- DoWrite(k, "");
- }
- public void Write(Kind k, string s) {
- Contract.Requires(s != null);
- DoWrite(k, " " + s);
- }
-
- public void Write(Type ty) {
- Contract.Requires(ty != null);
- if (ty.IsInt) {
- Write(B2I.Kind.Int);
- } else if (ty.IsBool) {
- Write(B2I.Kind.Bool);
- } else if (ty.IsBv) {
- Write(B2I.Kind.BvType, ty.BvBits.ToString());
- } else if (ty.IsVariable) {
- Write(B2I.Kind.TypeVar, ty.AsVariable.Name);
- } else if (ty.IsCtor) {
- CtorType t = ty.AsCtor;
- Contract.Assert(t != null);
- Write(B2I.Kind.TypeCon, t.Decl.Name + " " + t.Arguments.Length);
- Indent(2);
- foreach (Type a in t.Arguments) {
- Contract.Assert(a != null);
- Write(a);
- }
- Unindent();
- } else if (ty.IsMap) {
- MapType t = ty.AsMap;
- Contract.Assert(t != null);
- if (Context.AllTypes) {
- Write(B2I.Kind.Array, t.TypeParameters.Length + " " +
- (t.Arguments.Length + 1));
- Indent(2);
- foreach (TypeVariable v in t.TypeParameters) {
- Contract.Assert(v != null);
- Write(v);
- }
- Unindent();
- } else {
- Write(B2I.Kind.Array, (t.Arguments.Length + 1).ToString());
- }
- Indent(2);
- foreach (Type a in t.Arguments) {
- Contract.Assert(a != null);
- Write(a);
- }
- Write(t.Result);
- Unindent();
- }
- }
-
- public void Write(VCExpr e) {
- Contract.Requires(e != null);
- e.Accept<bool, B2I/*!*/>(exprWriter, this);
- }
- public void Write(VCExpr e, ProverInterface.ErrorHandler h) {
- Contract.Requires(e != null);
- Contract.Requires(h != null);
- eh = h;
- e.Accept<bool, B2I/*!*/>(exprWriter, this);
- eh = null;
- }
- public void Write(VCExprNAry e) {
- Contract.Requires(e != null);
- e.Accept<bool, B2I/*!*/>(exprOpWriter, this);
- }
-
- public B2I Write(QKeyValue atts, Boogie2VCExprTranslator tr) {
- Contract.Requires(tr != null);
- Contract.Ensures(Contract.Result<B2I>() != null);
-
- for (QKeyValue a = atts; a != null; a = a.Next) {
- Write(B2I.Kind.Attribute, a.Key + " " + a.Params.Count);
- Indent(2);
- foreach (object v in a.Params) {
- Contract.Assert(v != null);
- if (v is string) {
- string s = cce.NonNull((string)v).Replace("\n", " ").Replace("\r", " ")
- .Replace("\t", "\\w");
- Write(B2I.Kind.AttributeString, s);
- } else {
- Write(B2I.Kind.AttributeExpr);
- Indent(2);
- Write(tr.Translate(cce.NonNull((Expr)v)));
- Unindent();
- }
- }
- Unindent();
- }
- return this;
- }
-
- public enum Kind {
- TypeDecl,
- FunDecl,
- VarDecl,
- Axiom,
- VC,
- Attribute,
- AttributeString,
- AttributeExpr,
- Type,
- Int,
- Bool,
- BvType,
- TypeVar,
- TypeCon,
- Array,
- True,
- False,
- Not,
- And,
- Or,
- Implies,
- IfThenElse,
- Distinct,
- Eq,
- IntNumber,
- Le,
- Lt,
- Ge,
- Gt,
- Add,
- Sub,
- Mul,
- Div,
- Mod,
- BvNumber,
- BvExtract,
- BvConcat,
- Variable,
- Pat,
- NoPat,
- Forall,
- Exists,
- Select,
- Store,
- HeapSucc,
- Subtype,
- Subtype3,
- Function,
- Label
- };
-
- private string StringOfKind(Kind k) {
- Contract.Ensures(Contract.Result<string>() != null);
-
- switch (k) {
- case Kind.TypeDecl:
- return "type-decl";
- case Kind.FunDecl:
- return "fun-decl";
- case Kind.VarDecl:
- return "var-decl";
- case Kind.Axiom:
- return "axiom";
- case Kind.VC:
- return "vc";
-
- case Kind.Attribute:
- return "attribute";
- case Kind.AttributeString:
- return "string-attr";
- case Kind.AttributeExpr:
- return "expr-attr";
-
- case Kind.Type:
- return "type";
- case Kind.Int:
- return "int";
- case Kind.Bool:
- return "bool";
- case Kind.BvType:
- return "bv";
- case Kind.TypeVar:
- return "type-var";
- case Kind.TypeCon:
- return "type-con";
- case Kind.Array:
- return "array";
-
- case Kind.True:
- return "true";
- case Kind.False:
- return "false";
- case Kind.IntNumber:
- return "int-num";
- case Kind.BvNumber:
- return "bv-num";
- case Kind.Variable:
- return "var";
-
- case Kind.Not:
- return "not";
- case Kind.And:
- return "and";
- case Kind.Or:
- return "or";
- case Kind.Implies:
- return "implies";
- case Kind.IfThenElse:
- return "ite";
- case Kind.Distinct:
- return "distinct";
- case Kind.Eq:
- return "=";
- case Kind.Le:
- return "<=";
- case Kind.Lt:
- return "<";
- case Kind.Ge:
- return ">=";
- case Kind.Gt:
- return ">";
- case Kind.Add:
- return "+";
- case Kind.Sub:
- return "-";
- case Kind.Mul:
- return "*";
- case Kind.Div:
- return "/";
- case Kind.Mod:
- return "%";
- case Kind.Select:
- return "select";
- case Kind.Store:
- return "store";
- case Kind.BvExtract:
- return "bv-extract";
- case Kind.BvConcat:
- return "bv-concat";
- case Kind.HeapSucc:
- return "heap-succ";
- case Kind.Subtype:
- return "subtype";
- case Kind.Subtype3:
- return "subtype3";
-
- case Kind.Function:
- return "fun";
-
- case Kind.Label:
- return "label";
-
- case Kind.Pat:
- return "pat";
- case Kind.NoPat:
- return "nopat";
- case Kind.Forall:
- return "forall";
- case Kind.Exists:
- return "exists";
- }
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- public static int CountOf(QKeyValue atts) {
- int i = 0;
- for (QKeyValue a = atts; a != null; a = a.Next) {
- i++;
- }
- return i;
- }
-
- public static QKeyValue Add(string key, string value, QKeyValue kv) {
- Contract.Requires(key != null);
- Contract.Ensures(Contract.Result<QKeyValue>() != null);
-
-
- List<object/*!*/>/*!*/ list = new List<object/*!*/>();
- if (value != null) {
- list.Add(value);
- }
- return new QKeyValue(Token.NoToken, key, list, kv);
- }
- }
-
- class VCExprWriter : IVCExprVisitor<bool, B2I/*!*/> {
- public bool Visit(VCExprLiteral node, B2I b2i) {
- //Contract.Requires(node != null);
- //Contract.Requires(b2i != null);
-
- if (node == VCExpressionGenerator.True) {
- b2i.Write(B2I.Kind.True);
- } else if (node == VCExpressionGenerator.False) {
- b2i.Write(B2I.Kind.False);
- } else if (node is VCExprIntLit) {
- b2i.Write(B2I.Kind.IntNumber, ((VCExprIntLit)node).Val.ToString());
- } else
- Contract.Assert(false);
- return true;
- }
-
- public bool Visit(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- b2i.Write(node);
- return true;
- }
-
- public bool Visit(VCExprVar node, B2I b2i) {
- //Contract.Requires(node != null);
- //Contract.Requires(b2i != null);
- if (b2i.Context.IsFunctionDeclared(node.Name)) {
- b2i.Write(B2I.Kind.Function, node.Name + " 0");
- if (b2i.Context.AllTypes) {
- b2i.Indent(2);
- b2i.Write(node.Type);
- b2i.Unindent();
- }
- } else {
- b2i.Write(B2I.Kind.Variable, node.Name);
- b2i.Indent(2);
- b2i.Write(node.Type);
- b2i.Unindent();
- }
- return true;
- }
-
- public bool Visit(VCExprQuantifier node, B2I b2i) {
- //Contract.Requires(node != null);
- //Contract.Requires(b2i != null);
- QKeyValue attribs =
- B2I.Add("qid", node.Infos.qid,
- B2I.Add("uniqueId", node.Infos.uniqueId.ToString(),
- B2I.Add("bvZ3Native", node.Infos.bvZ3Native.ToString(),
- node.Infos.attributes)));
-
- B2I.Kind all = B2I.Kind.Forall;
- B2I.Kind ex = B2I.Kind.Exists;
- if (b2i.Context.AllTypes) {
- b2i.Write((node.Quan == Quantifier.ALL) ? all : ex,
- node.TypeParameters.Count + " " + node.BoundVars.Count + " " +
- node.Triggers.Count + " " + B2I.CountOf(attribs));
- b2i.Indent(2);
- foreach (TypeVariable v in node.TypeParameters) {
- Contract.Assert(v != null);
- b2i.Write(v);
- }
- b2i.Unindent();
- } else {
- b2i.Write((node.Quan == Quantifier.ALL) ? all : ex,
- node.BoundVars.Count + " " + node.Triggers.Count + " " +
- B2I.CountOf(attribs));
- }
- b2i.Indent(2);
- foreach (VCExprVar v in node.BoundVars) {
- Contract.Assert(v != null);
- b2i.Write(B2I.Kind.Variable, v.Name);
- b2i.Indent(2);
- b2i.Write(v.Type);
- b2i.Unindent();
- }
- foreach (VCTrigger t in node.Triggers) {
- Contract.Assert(t != null);
- B2I.Kind k = (t.Pos) ? B2I.Kind.Pat : B2I.Kind.NoPat;
- b2i.Write(k, t.Exprs.Count.ToString());
- b2i.Indent(2);
- foreach (VCExpr e in t.Exprs) {
- Contract.Assert(e != null);
- b2i.Write(e);
- }
- b2i.Unindent();
- }
- b2i.Write(attribs, b2i.Context.BoogieExprTranslator);
- b2i.Unindent();
- b2i.Write(node.Body);
- return true;
- }
-
- public bool Visit(VCExprLet node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- // we do not support "let"
- Contract.Assert(false);
- return true;
- }
- }
-
- class VCExprOpWriter : IVCExprOpVisitor<bool, B2I/*!*/> {
- private void WriteArguments(B2I b2i, VCExprNAry node) {
- Contract.Requires(node!=null);
- Contract.Requires(b2i != null);
- foreach (VCExpr e in node) {
- b2i.Write(e);
- }
- }
- private bool Write(B2I b2i, B2I.Kind k, VCExprNAry node) {
- Contract.Requires(node!=null);
- Contract.Requires(b2i != null);
- b2i.Write(k);
- WriteArguments(b2i, node);
- return true;
- }
-
- public bool VisitNotOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Not, node);
- }
- public bool VisitEqOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- b2i.Write(B2I.Kind.Eq);
- if (b2i.Context.AllTypes) {
- b2i.Indent(2);
- b2i.Write(node[0].Type);
- b2i.Unindent();
- }
- WriteArguments(b2i, node);
- return true;
- }
- public bool VisitNeqOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- b2i.Write(B2I.Kind.Not);
- b2i.Write(B2I.Kind.Eq);
- if (b2i.Context.AllTypes) {
- b2i.Indent(2);
- b2i.Write(node[0].Type);
- b2i.Unindent();
- }
- WriteArguments(b2i, node);
- return true;
- }
- private bool Unroll(B2I.Kind kind, VCExprNAry node, B2I b2i) {
- Contract.Requires(node!=null);
- Contract.Requires(b2i != null);
- List<VCExpr/*!>!*/> unroll = new List<VCExpr/*!*/>();
- foreach (VCExpr e in node) {
- unroll.Insert(0, e);
- }
-
- List<VCExpr/*!>!*/> flat = new List<VCExpr/*!*/>();
-
- while (unroll.Count > 0) {
- VCExpr hd = unroll[0];
- Contract.Assert(hd != node);
- unroll.RemoveAt(0);
- if (hd is VCExprNAry && ((VCExprNAry)hd).Op.Equals(node.Op)) {
- VCExprNAry n = (VCExprNAry)hd;
- foreach (VCExpr e in n) {
- Contract.Assert(e != null);
- unroll.Insert(0, e);
- }
- } else {
- flat.Insert(0, hd);
- }
- }
-
- b2i.Write(kind, flat.Count.ToString());
- foreach (VCExpr e in flat) {
- Contract.Assert(e != null);
- b2i.Write(e);
- }
- return true;
- }
- public bool VisitAndOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node != null);
- //Contract.Requires(b2i != null);
- return Unroll(B2I.Kind.And, node, b2i);
- }
- public bool VisitOrOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Unroll(B2I.Kind.Or, node, b2i);
- }
- public bool VisitImpliesOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Implies, node);
- }
- public bool VisitDistinctOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- b2i.Write(B2I.Kind.Distinct, node.Length.ToString());
- if (b2i.Context.AllTypes) {
- b2i.Indent(2);
- b2i.Write(node[0].Type);
- b2i.Unindent();
- }
- WriteArguments(b2i, node);
- return true;
- }
-
- public bool VisitLabelOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node != null);
- //Contract.Requires(b2i != null);
- VCExprLabelOp op = (VCExprLabelOp)node.Op;
- Contract.Assert(op != null);
- string label = op.label.Substring(1);
- int ln = 0;
- int col = 0;
- if (b2i.LabelRenamer != null) {
- Absy absy = b2i.LabelRenamer.Label2Absy(label);
- Contract.Assert(absy != null);
- if (absy.Line > 0 && absy.Col > 0) {
- ln = absy.Line;
- col = absy.Col;
- }
- }
- string k = ((op.pos) ? "pos" : "neg");
- b2i.Write(B2I.Kind.Label, k + " " + ln + " " + col);
- WriteArguments(b2i, node);
- return true;
- }
-
- public bool VisitSelectOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node != null);
- //Contract.Requires(b2i != null);
- b2i.Write(B2I.Kind.Select, node.Length.ToString());
- if (b2i.Context.AllTypes) {
- b2i.Indent(2);
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- b2i.Write(e.Type);
- }
- b2i.Unindent();
- }
- Contract.Assert(node.Type.Equals(node[0].Type.AsMap.Result));
- WriteArguments(b2i, node);
- return true;
- }
- public bool VisitStoreOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node != null);
- //Contract.Requires(b2i != null);
- b2i.Write(B2I.Kind.Store, node.Length.ToString());
- if (b2i.Context.AllTypes) {
- b2i.Indent(2);
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- b2i.Write(e.Type);
- }
- b2i.Unindent();
- }
- Contract.Assert(node.Type.Equals(node[0].Type));
- WriteArguments(b2i, node);
- return true;
- }
-
- public bool VisitBvOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node != null);
- //Contract.Requires(b2i != null);
- VCExprIntLit num = node[0] as VCExprIntLit;
- if (num == null) {
- Contract.Assert(false);
- }
- b2i.Write(B2I.Kind.BvNumber, node.Type.BvBits + " " + num.Val);
- return true;
- }
- public bool VisitBvExtractOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- VCExprBvExtractOp op = (VCExprBvExtractOp)node.Op;
- Contract.Assert(op != null);
- VCExpr child = node[0];
- Contract.Assert(child != null);
-
- b2i.Write(B2I.Kind.BvExtract, op.End + " " + op.Start);
- if (b2i.Context.AllTypes) {
- b2i.Indent(2);
- b2i.Write(child.Type);
- b2i.Write(node.Type);
- b2i.Unindent();
- }
- b2i.Write(child);
- return true;
- }
- public bool VisitBvConcatOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node != null);
- //Contract.Requires(b2i != null);
- //Contract.Requires(node.Length >= 2);
-
- VCExpr child1 = node[0];
- Contract.Assert(child1 != null);
- VCExpr child2 = node[1];
- Contract.Assert(child2 != null);
- b2i.Write(B2I.Kind.BvConcat);
- if (b2i.Context.AllTypes) {
- b2i.Indent(2);
- b2i.Write(child1.Type);
- b2i.Write(child2.Type);
- b2i.Write(node.Type);
- b2i.Unindent();
- }
- b2i.Write(child1);
- b2i.Write(child2);
- return true;
- }
-
- public bool VisitIfThenElseOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node != null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.IfThenElse, node);
- }
-
- public bool VisitCustomOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node != null);
- //Contract.Requires(b2i != null);
- VCExprCustomOp op = (VCExprCustomOp)node.Op;
-
- Contract.Assert(op.Arity == node.Length);
- b2i.Write(B2I.Kind.Function, op.Name + " " + node.Length);
- if (b2i.Context.AllTypes) {
- b2i.Indent(2);
-
- // pick the types from the actual arguments
- foreach (VCExpr arg in node) {
- Contract.Assert(arg != null);
- b2i.Write(arg.Type);
- }
- b2i.Unindent();
- }
- if (b2i.Context.AllTypes) {
- b2i.Indent(2);
- b2i.Write(op.Type);
- b2i.Unindent();
- }
- WriteArguments(b2i, node);
- return true;
- }
-
- public bool VisitHeapSuccessionOp(VCExprNAry node, B2I b2i) {
- Contract.Requires(node != null);
- Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.HeapSucc, node);
- }
-
- public bool VisitAddOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node != null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Add, node);
- }
- public bool VisitSubOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Sub, node);
- }
- public bool VisitMulOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Mul, node);
- }
- public bool VisitDivOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Div, node);
- }
- public bool VisitModOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Mod, node);
- }
- public bool VisitLtOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Lt, node);
- }
- public bool VisitLeOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Le, node);
- }
- public bool VisitGtOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Gt, node);
- }
- public bool VisitGeOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Ge, node);
- }
-
- public bool VisitSubtypeOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Subtype, node);
- }
- public bool VisitSubtype3Op(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- return Write(b2i, B2I.Kind.Subtype3, node);
- }
-
- public bool VisitBoogieFunctionOp(VCExprNAry node, B2I b2i) {
- //Contract.Requires(node!=null);
- //Contract.Requires(b2i != null);
- Function f = cce.NonNull((VCExprBoogieFunctionOp)node.Op).Func;
-
- Contract.Assert(f.InParams.Length == node.Length);
- b2i.Write(B2I.Kind.Function, f.Name + " " + node.Length);
- if (b2i.Context.AllTypes) {
- b2i.Indent(2);
-
- foreach (Variable v in f.InParams) {
- Contract.Assert(v != null);
- b2i.Write(v.TypedIdent.Type);
- }
- b2i.Unindent();
- }
- Contract.Assert(f.OutParams.Length == 1);
- Contract.Assert(f.OutParams[0] != null);
- if (b2i.Context.AllTypes) {
- b2i.Indent(2);
- b2i.Write(cce.NonNull((Variable)f.OutParams[0]).TypedIdent.Type);
- b2i.Unindent();
- }
- WriteArguments(b2i, node);
- return true;
- }
-
-
-
- }
-} \ No newline at end of file
diff --git a/Source/Provers/Isabelle/cce.cs b/Source/Provers/Isabelle/cce.cs
deleted file mode 100644
index ef594484..00000000
--- a/Source/Provers/Isabelle/cce.cs
+++ /dev/null
@@ -1,193 +0,0 @@
-using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
- }
- //[Pure]
- //public static bool NonNullElements(VariableSeq collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
-} \ No newline at end of file
diff --git a/Source/Provers/SMTLib/SMTLib.csproj b/Source/Provers/SMTLib/SMTLib.csproj
index 3dc042a6..c2d68fc8 100644
--- a/Source/Provers/SMTLib/SMTLib.csproj
+++ b/Source/Provers/SMTLib/SMTLib.csproj
@@ -159,10 +159,6 @@
<Compile Include="Z3.cs" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
<ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
<Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
<Name>Basetypes</Name>
diff --git a/Source/Provers/SMTLib/SMTLibLineariser.cs b/Source/Provers/SMTLib/SMTLibLineariser.cs
index 6a2cbb6a..cf125c76 100644
--- a/Source/Provers/SMTLib/SMTLibLineariser.cs
+++ b/Source/Provers/SMTLib/SMTLibLineariser.cs
@@ -115,7 +115,7 @@ namespace Microsoft.Boogie.SMTLib
}
sb.Append(']');
TypeToStringHelper(m.Result, sb);
- } else if (t.IsBool || t.IsInt || t.IsBv) {
+ } else if (t.IsBool || t.IsInt || t.IsReal || t.IsBv) {
sb.Append(TypeToString(t));
} else {
System.IO.StringWriter buffer = new System.IO.StringWriter();
@@ -137,6 +137,8 @@ namespace Microsoft.Boogie.SMTLib
return "Bool";
else if (t.IsInt)
return "Int";
+ else if (t.IsReal)
+ return "Real";
else if (t.IsBv) {
return "(_ BitVec " + t.BvBits + ")";
} else {
@@ -181,7 +183,16 @@ namespace Microsoft.Boogie.SMTLib
wr.Write("(- 0 {0})", lit.Abs);
else
wr.Write(lit);
- } else {
+ }
+ else if (node is VCExprRealLit) {
+ BigDec lit = ((VCExprRealLit)node).Val;
+ if (lit.IsNegative)
+ // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols")
+ wr.Write("(- 0.0 {0})", lit.Abs.ToDecimalString(20));
+ else
+ wr.Write(lit.ToDecimalString(20));
+ }
+ else {
Contract.Assert(false);
throw new cce.UnreachableException();
}
@@ -609,13 +620,23 @@ namespace Microsoft.Boogie.SMTLib
public bool VisitDivOp(VCExprNAry node, LineariserOptions options)
{
- WriteApplication("int_div", node, options);
+ WriteApplication("div", node, options);
return true;
}
public bool VisitModOp(VCExprNAry node, LineariserOptions options)
{
- WriteApplication("int_mod", node, options);
+ WriteApplication("mod", node, options);
+ return true;
+ }
+
+ public bool VisitRealDivOp(VCExprNAry node, LineariserOptions options) {
+ WriteApplication("/", node, options);
+ return true;
+ }
+
+ public bool VisitPowOp(VCExprNAry node, LineariserOptions options) {
+ WriteApplication("real_pow", node, options);
return true;
}
@@ -655,6 +676,16 @@ namespace Microsoft.Boogie.SMTLib
return true;
}
+ public bool VisitToIntOp(VCExprNAry node, LineariserOptions options) {
+ WriteApplication("to_int", node, options);
+ return true;
+ }
+
+ public bool VisitToRealOp(VCExprNAry node, LineariserOptions options) {
+ WriteApplication("to_real", node, options);
+ return true;
+ }
+
private string ExtractDatatype(Function func) {
if (func is DatatypeSelector) {
DatatypeSelector selector = (DatatypeSelector) func;
diff --git a/Source/Provers/SMTLib/SMTLibNamer.cs b/Source/Provers/SMTLib/SMTLibNamer.cs
index 5629c0d6..101b07a0 100644
--- a/Source/Provers/SMTLib/SMTLibNamer.cs
+++ b/Source/Provers/SMTLib/SMTLibNamer.cs
@@ -22,8 +22,8 @@ namespace Microsoft.Boogie.SMTLib
// Core theory:
"and", "or", "not", "iff", "true", "false", "xor", "distinct", "ite", "=", "Bool",
"=>", // implies (sic!)
- // Integers
- "Int", "*", "/", "-", "+", "<", "<=", ">", ">=",
+ // Integers and reals
+ "Int", "Real", "*", "/", "-", "+", "<", "<=", ">", ">=", "div", "mod",
// Bitvectors
"extract", "concat",
"bvnot", "bvneg", "bvand", "bvor", "bvadd", "bvmul", "bvudiv", "bvurem", "bvshl", "bvlshr", "bvult",
@@ -48,7 +48,7 @@ namespace Microsoft.Boogie.SMTLib
"lblneg", "lblpos", "lbl-lit",
"if", "&&", "||", "equals", "equiv", "bool",
// Boogie-defined
- "int_mod", "int_div", "UOrdering2", "UOrdering3",
+ "real_pow", "UOrdering2", "UOrdering3",
};
static HashSet<string> reservedSmtWords;
diff --git a/Source/Provers/SMTLib/TypeDeclCollector.cs b/Source/Provers/SMTLib/TypeDeclCollector.cs
index a4bdee51..bff949ea 100644
--- a/Source/Provers/SMTLib/TypeDeclCollector.cs
+++ b/Source/Provers/SMTLib/TypeDeclCollector.cs
@@ -255,7 +255,7 @@ void ObjectInvariant()
return;
}
- if (type.IsBool || type.IsInt || type.IsBv)
+ if (type.IsBool || type.IsInt || type.IsReal || type.IsBv)
return;
CtorType ctorType = type as CtorType;
diff --git a/Source/Provers/Simplify/Let2ImpliesVisitor.cs b/Source/Provers/Simplify/Let2ImpliesVisitor.cs
deleted file mode 100644
index 9b8328d1..00000000
--- a/Source/Provers/Simplify/Let2ImpliesVisitor.cs
+++ /dev/null
@@ -1,236 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.Simplify
-{
- // Simplify does not understand the LET operator, so we have to replace
- // it with implications (previously, this was done in the VCExprGenerator), or
- // we have to apply the let as a substitution (in the case of terms)
-
- // This visitor expects that let-bindings are sorted, so that bound
- // variables only occur after their declaration
-
- public class Let2ImpliesMutator : SubstitutingVCExprVisitor {
-
- public Let2ImpliesMutator(VCExpressionGenerator gen) :base(gen) {
- Contract.Requires(gen!=null);
- this.keepLetFormula = this.keepLetTerm = false;
- }
-
- public Let2ImpliesMutator(VCExpressionGenerator gen, bool keepLetTerm, bool keepLetFormula):base(gen) {
- Contract.Requires(gen!=null);
-
- this.keepLetTerm = keepLetTerm;
- this.keepLetFormula = keepLetFormula;
- }
-
- readonly bool keepLetTerm;
- readonly bool keepLetFormula;
-
- public VCExpr Mutate(VCExpr expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Mutate(expr, new VCExprSubstitution ());
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private int polarity = 1; // 1 for positive, -1 for negative, 0 for both
-
- // we also track which variables occur in positive, negative, or
- // in both positions (to decide whether implications or equations
- // have to be used to define such a variable)
- private enum OccurrenceTypes { None, Pos, Neg, PosNeg };
- private OccurrenceTypes Union(OccurrenceTypes o1, OccurrenceTypes o2) {
- switch(o1) {
- case OccurrenceTypes.None: return o2;
- case OccurrenceTypes.Pos:
- switch(o2) {
- case OccurrenceTypes.None:
- case OccurrenceTypes.Pos:
- return OccurrenceTypes.Pos;
- default:
- return OccurrenceTypes.PosNeg;
- }
- case OccurrenceTypes.Neg:
- switch(o2) {
- case OccurrenceTypes.None:
- case OccurrenceTypes.Neg:
- return OccurrenceTypes.Neg;
- default:
- return OccurrenceTypes.PosNeg;
- }
- default:
- return OccurrenceTypes.PosNeg;
- }
- }
-
- private IDictionary<VCExprVar/*!*/, OccurrenceTypes>/*!*/ VarOccurrences =
- new Dictionary<VCExprVar/*!*/, OccurrenceTypes>();
- [ContractInvariantMethod]
-void ObjectInvariant()
-{
- Contract.Invariant(VarOccurrences != null);
-}
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprVar node,
- VCExprSubstitution substitution) {
- Contract.Requires(node!= null);
- Contract.Requires(substitution != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpr res = base.Visit(node, substitution);
- Contract.Assert(res!=null);
-
- VCExprVar resAsVar = res as VCExprVar;
- if (resAsVar != null) {
- OccurrenceTypes occ;
- if (polarity > 0)
- occ = OccurrenceTypes.Pos;
- else if (polarity < 0)
- occ = OccurrenceTypes.Neg;
- else
- occ = OccurrenceTypes.PosNeg;
-
- OccurrenceTypes oldOcc;
- if (VarOccurrences.TryGetValue(resAsVar, out oldOcc))
- occ = Union(occ, oldOcc);
- VarOccurrences[resAsVar] = occ;
- }
-
- return res;
- }
-
- public override VCExpr Visit(VCExprNAry node,
- VCExprSubstitution substitution) {
- Contract.Requires(node != null);
- Contract.Requires(substitution != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- // track the polarity to ensure that no implications are introduced
- // in negative positions
- // UGLY: the code for tracking polarities should be factored out
- // (similar code is used in the TypeEraser)
-
- VCExpr res;
- if (node.Op.Equals(VCExpressionGenerator.NotOp)) {
- polarity = -polarity;
- res = base.Visit(node, substitution);
- polarity = -polarity;
- } else if (node.Op.Equals(VCExpressionGenerator.ImpliesOp)) {
- polarity = -polarity;
- VCExpr newArg0 = Mutate(node[0], substitution);
- Contract.Assert(newArg0 != null);
- polarity = -polarity;
- VCExpr newArg1 = Mutate(node[1], substitution);
- Contract.Assert(newArg1 != null);
-
- res = Gen.Implies(newArg0, newArg1);
- } else if (!node.Op.Equals(VCExpressionGenerator.AndOp) &&
- !node.Op.Equals(VCExpressionGenerator.OrOp) &&
- !(node.Op is VCExprLabelOp)) {
- // standard is to set the polarity to 0 (fits most operators)
- int oldPolarity = polarity;
- polarity = 0;
- res = base.Visit(node, substitution);
- polarity = oldPolarity;
- } else {
- res = base.Visit(node, substitution);
- }
-
- return res;
- }
-
- public override VCExpr Visit(VCExprLet originalNode,
- VCExprSubstitution substitution) {
- Contract.Requires(originalNode != null);
- Contract.Requires(substitution != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- // first sort the bindings to be able to apply substitutions
- LetBindingSorter letSorter = new LetBindingSorter (Gen);
- Contract.Assert(letSorter != null);
- VCExpr newNode = letSorter.Mutate(originalNode, true);
- Contract.Assert(newNode != null);
- VCExprLet node = newNode as VCExprLet;
-
- if (node == null)
- // it can happen that the complete let-expressions gets eliminated by the
- // sorter, which also checks whether let-bindings are actually used
- return newNode;
-
- substitution.PushScope(); try {
-
- // the bindings that remain and that are later handled using an implication
- List<VCExprLetBinding> bindings = new List<VCExprLetBinding> ();
- List<VCExprLetBinding> keepBindings = new List<VCExprLetBinding> ();
-
- foreach (VCExprLetBinding binding in node) {
- Contract.Assert(binding != null);
- // in all cases we apply the substitution up to this point
- // to the bound formula
- VCExpr newE = Mutate(binding.E, substitution);
- Contract.Assert(newE != null);
- if (binding.V.Type.IsBool) {
- // a bound formula is handled using an implication; we introduce
- // a fresh variable to avoid clashes
- Contract.Assert( polarity > 0);
-
- if (keepLetFormula) {
- keepBindings.Add(Gen.LetBinding(binding.V, newE));
-
- } else {
- VCExprVar newVar = Gen.Variable(binding.V.Name, Type.Bool);
- Contract.Assert(newVar != null);
- substitution[binding.V] = newVar;
-
- bindings.Add(Gen.LetBinding(newVar, newE));
- }
- } else {
- if (keepLetTerm) {
- keepBindings.Add(Gen.LetBinding(binding.V, newE));
- } else {
- // a bound term is substituted
- substitution[binding.V] = newE;
- }
- }
- }
-
- VCExpr newBody = Mutate(node.Body, substitution);
- Contract.Assert(newBody != null);
- if (keepBindings.Count > 0) {
- newBody = Gen.Let(keepBindings, newBody);
- }
-
- // Depending on the places where the variable occurs, we would
- // have to introduce implications or equations to define the
- // bound variables. For the time being, we just assert that all
- // occurrences are positive
- foreach (VCExprLetBinding b in bindings) {
- Contract.Assert(b != null);
- OccurrenceTypes occ;
- if (VarOccurrences.TryGetValue(b.V, out occ))
- Contract.Assert( occ == OccurrenceTypes.None || occ == OccurrenceTypes.Pos);
- }
-
- return Gen.ImpliesSimp(Gen.AsImplications(bindings), newBody);
-
- } finally {
- substitution.PopScope();
- }
- }
- }
-
-} \ No newline at end of file
diff --git a/Source/Provers/Simplify/Prover.cs b/Source/Provers/Simplify/Prover.cs
deleted file mode 100644
index 3faa18e1..00000000
--- a/Source/Provers/Simplify/Prover.cs
+++ /dev/null
@@ -1,656 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.IO;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using System.Collections;
-using System.Collections.Generic;
-//using util;
-using Microsoft.Boogie;
-
-// Simplified interface to an external prover like Simplify or the z3 process, taken from Bird.
-namespace Microsoft.Boogie.Simplify {
- /// <summary>
- /// An interface to Simplify theorem prover.
- /// </summary>
- ///
- [ContractClass(typeof(ProverProcessContracts))]
- public abstract class ProverProcess {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(simplify != null);
- Contract.Invariant(fromSimplify != null);
- Contract.Invariant(toSimplify != null);
- Contract.Invariant(fromStdError != null);
- }
-
- [Rep]
- protected readonly Process simplify;
-
- [Rep]
- readonly TextReader fromSimplify;
- [Rep]
- readonly TextWriter toSimplify;
- [Rep]
- readonly TextReader fromStdError;
-
- protected bool readTimedOut;
-
- int nFormulasChecked = 0;
- public int NumFormulasChecked {
- get {
- return nFormulasChecked;
- }
- }
-
- // Note: In the Everett build (.NET framework < 2.0), Process.PeakVirtualMemorySize64
- // is not defined, but rather a version that returns an 'int' rather than a 'long'.
- public long PeakVirtualMemorySize {
- [NoDefaultContract]
- get
- //modifies this.*;
- {
- Contract.Requires(cce.IsPeerConsistent(this));
- try {
- cce.BeginExpose(this);
- simplify.Refresh();
-#if WHIDBEY
- return simplify.PeakVirtualMemorySize64;
-#else
- return simplify.PeakPagedMemorySize64;
-#endif
- } finally {
- cce.EndExpose();
- }
- }
- }
-
- public bool HasExited {
- get {
- return simplify.HasExited;
- }
- }
-
- public ProverProcess(ProcessStartInfo psi, string proverPath) { // throws ProverException
- Contract.Requires(psi != null);
- Contract.Requires(proverPath != null);
- try {
- Process simplify = Process.Start(psi);
- this.simplify = simplify;
- fromSimplify = simplify.StandardOutput;
- toSimplify = simplify.StandardInput;
- fromStdError = simplify.StandardError;
- } catch (System.ComponentModel.Win32Exception e) {
- throw new ProverException(string.Format("Unable to start the process {0}: {1}", proverPath, e.Message));
- }
- // base();
- }
-
- public abstract string OptionComments();
-
- //[Pure(false)]
- public virtual IEnumerable<string/*!>!*/> ParameterSettings {
- get {
- yield break;
- }
- }
-
- public void Close()
- //modifies this.*;
- {
- cce.BeginExpose(this);
- {
- toSimplify.Flush();
- if (this.simplify != null) {
- if (!simplify.HasExited) {
- this.Kill();
- }
- simplify.Close();
- }
- }
- cce.EndExpose();
- }
-
- [NoDefaultContract] // this method assumes nothing about the object, other than that it has been constructed (which means simplify!=null)
- [Verify(false)] // The call simplify.Kill will require simplify.IsPeerConsistent, but since we don't know the state of "this" and "simplify", we cannot afford the run-time check that an assume statement here would impose
- public void Kill() {
- try {
- if (CommandLineOptions.Clo.ProverShutdownLimit > 0) {
- toSimplify.Close();
- for (int i = 0; !simplify.HasExited && i <= CommandLineOptions.Clo.ProverShutdownLimit * 1000; i += 100) {
- System.Threading.Thread.Sleep(100);
- }
- }
- if (!simplify.HasExited) {
- simplify.Kill();
- }
- } catch (InvalidOperationException) { /* already exited */
- } catch (System.ComponentModel.Win32Exception) { /* already exiting */
- }
- }
-
- public virtual void AddAxioms(string s)
- //modifies this.*;
- //modifies Console.Out.*, Console.Error.*;
- {
- Contract.Requires(s != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- cce.BeginExpose(this);
- toSimplify.Write("(BG_PUSH ");
- toSimplify.Write(s);
- toSimplify.WriteLine(")");
- cce.EndExpose();
- }
-
- public virtual void Feed(string s, int statementCount)
- //modifies this.*;
- //modifies Console.Out.*, Console.Error.*;
- {
- Contract.Requires(s != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- cce.BeginExpose(this);
- {
- toSimplify.Write(s);
- }
- cce.EndExpose();
- }
-
- public virtual void PopAxioms()
- //modifies this.*;
- //modifies Console.Out.*, Console.Error.*;
- {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- cce.BeginExpose(this);
- {
- toSimplify.WriteLine("(BG_POP)");
- }
- cce.EndExpose();
- }
-
- public void ToFlush()
- //modifies this.*;
- {
- cce.BeginExpose(this);
- {
- toSimplify.Flush();
- }
- cce.EndExpose();
- }
-
- public enum ProverOutcome {
- Valid,
- NotValid,
- TimeOut,
- OutOfMemory,
- Inconclusive
- }
-
- /// <summary>
- /// Passes the formula to Simplify.
- /// </summary>
- public void BeginCheck(string descriptiveName, string formula)
- //modifies this.*;
- //modifies Console.Out.*, Console.Error.*;
- {
- Contract.Requires(descriptiveName != null);
- Contract.Requires(formula != null);
- DoBeginCheck(descriptiveName, formula);
- nFormulasChecked++;
- }
-
- /// <summary>
- /// Reports the outcome of formula checking. If the outcome is Invalid,
- /// then the "handler" is invoked with each counterexample.
- /// </summary>
- public abstract ProverOutcome CheckOutcome(Microsoft.Boogie.ProverInterface.ErrorHandler handler);
- //modifies this.**;
- //modifies Console.Out.*, Console.Error.*;
- //modifies handler.*;
-
- protected abstract void DoBeginCheck(string descriptiveName, string formula);
- //modifies this.*;
- //modifies Console.Out.*, Console.Error.*;
-
- /// <summary>
- /// Returns an array of the labels in "labels", with "|" brackets (if any)
- /// stripped off.
- /// Assumes that every label begins with "|+" or "|@", or just "+" or "@",
- /// and ends with "|" if it started with one, and that these "|" brackets are
- /// the only "|"s in "labels".
- /// </summary>
- protected static List<string/*!>!*/> ParseLabels(string labels) {
- Contract.Requires(labels != null);
- Contract.Ensures(Contract.Result<List<string>>() != null);
-
- List<string> list = new List<string>();
- int j = 0;
- while (true)
- // invariant: j is the number of characters of "labels" consumed so far
- // invariant: an even number of '|' characters remain in "labels"
- {
- cce.LoopInvariant(0 <= j && j <= labels.Length);
- j = labels.IndexOfAny(new char[] { '|', '+', '@' }, j);
- if (j < 0) {
- // no more labels
- return list;
- }
- char ch = labels[j];
- if (ch == '|') {
- j++; // skip the '|'
- Contract.Assume(j < labels.Length); // there should now be a '+' or '@'
- ch = labels[j];
- }
- Contract.Assume(ch == '+' || ch == '@');
- j++; // skip the '+' or '@'
- int k = labels.IndexOfAny(new char[] { '|', ' ', ')' }, j);
- Contract.Assume(j + 2 <= k);
- string s = labels.Substring(j, k - j);
- list.Add(s);
- j = k + 1;
- }
- }
-
- [Rep]
- char[] expectBuffer = null;
-
- /// <summary>
- /// Expects s[0]==ch and the next s.Length-1 characters of the input to be s[1,..]
- /// If not, more characters may be read from "fromSimplify" to provide additional context
- /// for the UnexpectedProverOutputException exception that will be thrown.
- /// </summary>
- protected void Expect(int ch, string s)
- //modifies this.*;
- {
- Contract.Requires(s != null);
- Contract.Requires(1 <= s.Length);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- if (ch == -1) {
- // a return of -1 from FromReadChar means that there is no StdOutput
- // to treat this we can return the error message we get from Z3 on StdError and then
- // declare this case to be inconclusive
- string str = FromStdErrorAll();
- if (str == "") {
- throw new ProverDiedException();
- } else {
- throw new UnexpectedProverOutputException("Expected \"" + s + "\", found:\r\n<<<start>>>\r\n" + str + "<<<end>>>");
- }
- }
-
- string badInputPrefix;
- if (ch != s[0]) {
- badInputPrefix = Char.ToString((char)ch);
- } else {
- int len = s.Length - 1;
- if (expectBuffer == null || expectBuffer.Length < len) {
- cce.BeginExpose(this);
- {
- expectBuffer = new char[len];
- }
- cce.EndExpose();
- }
- try {
- string s0;
- cce.BeginExpose(this);
- {
- fromSimplify.ReadBlock(expectBuffer, 0, len);
- s0 = new string(expectBuffer, 0, len);
- }
- cce.EndExpose();
- string s1 = s.Substring(1, len);
- if (s0.CompareTo(s1) == 0) {
- badInputPrefix = null; // no error
- } else {
- badInputPrefix = (char)ch + s0;
- }
- } catch (IOException) {
- throw new UnexpectedProverOutputException("Expected \"" + s + "\", encountered IO exception.");
- }
- }
-
- if (badInputPrefix != null) {
- // Read the rest of the available input, without blocking!
- // Despite the confusing documentation for the Read method, it seems
- // that Read does block. It if didn't, I would have written:
- // string remaining = "";
- // char[] buf = new char[1024];
- // while (true) {
- // int len = fromSimplify.Read(buf, 0, buf.Length);
- // remaining += new String(buf, 0, len);
- // if (len != buf.Length) {
- // break;
- // }
- // }
- // But instead, I'll just hope that one line of input is available and read
- // it.
- string remaining = fromSimplify.ReadLine() + "\r\n";
- throw new UnexpectedProverOutputException("Expected \"" + s + "\", found:\r\n<<<start>>>\r\n" + badInputPrefix + remaining + "<<<end>>>");
- }
- }
-
- protected int FromReadChar()
- //modifies this.*;
- {
- try {
- cce.BeginExpose(this);
- return fromSimplify.Read();
- } finally {
- cce.EndExpose();
- }
- }
-
- private void KillProver(object state) {
- cce.BeginExpose(this);
- {
- this.readTimedOut = true;
- simplify.Kill();
- }
- cce.EndExpose();
- }
-
- protected int FromReadChar(int timeout)
- //modifies this.*;
- {
- Contract.Requires(-1 <= timeout);
- try {
- cce.BeginExpose(this);
- this.readTimedOut = false;
- System.Threading.Timer t = new System.Threading.Timer(this.KillProver, null, timeout, System.Threading.Timeout.Infinite);
- int ch = fromSimplify.Read();
- t.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
- t.Dispose();
- return ch;
- } finally {
- cce.EndExpose();
- }
- }
-
- protected string FromReadLine()
- //modifies this.*;
- {
- Contract.Ensures(Contract.Result<string>() != null);
- try {
- cce.BeginExpose(this);
- string s = fromSimplify.ReadLine();
- if (s == null) {
- // this is what ReadLine returns if all characters have been read
- s = "";
- }
- return s;
- } finally {
- cce.EndExpose();
- }
- }
-
- protected string FromStdErrorAll()
- //modifies this.*;
- {
- Contract.Ensures(Contract.Result<string>() != null);
-
- try {
- cce.BeginExpose(this);
- if (fromStdError != null) {
- string s = fromStdError.ReadToEnd();
- if (s == null) {
- // this is what ReadLine returns if all characters have been read
- s = "";
- }
- return s;
- } else {
- // there is no StdErrorReader available
- return "";
- }
- } finally {
- cce.EndExpose();
- }
- }
-
- protected void ToWriteLine(string s)
- //modifies this.*;
- {
- Contract.Requires(s != null);
- cce.BeginExpose(this);
- {
- toSimplify.WriteLine(s);
- }
- cce.EndExpose();
- }
- }
- [ContractClassFor(typeof(ProverProcess))]
- public abstract class ProverProcessContracts : ProverProcess {
- private ProverProcessContracts() : base(null, null) { }
- public override string OptionComments() {
- Contract.Ensures(Contract.Result<string>() != null);
- throw new NotImplementedException();
- }
-
- public override ProverProcess.ProverOutcome CheckOutcome(ProverInterface.ErrorHandler handler) {
- Contract.Requires(handler != null);
- throw new NotImplementedException();
- }
-
- protected override void DoBeginCheck(string descriptiveName, string formula) {
- Contract.Requires(descriptiveName != null);
- Contract.Requires(formula != null);
- throw new NotImplementedException();
- }
- }
- // derived by Z3ProverProcess
- public class SimplifyProverProcess : ProverProcess {
- public SimplifyProverProcess(string proverPath, bool dummy) :base(getPSI(proverPath),proverPath) {
- Contract.Requires(proverPath != null);
- // throws ProverException
- }
- private static ProcessStartInfo getPSI(string proverPath){ProcessStartInfo psi = new ProcessStartInfo(proverPath, "-labelsonly");
- psi.CreateNoWindow = true;
- psi.UseShellExecute = false;
- psi.RedirectStandardInput = true;
- psi.RedirectStandardOutput = true;
- psi.RedirectStandardError = true;
- Contract.Assume(psi.EnvironmentVariables != null); // by inspecting the code through Reflector; the documentation says this property is "null by default", whatever that means --KRML
- if (0 <= CommandLineOptions.Clo.ProverKillTime) {
- psi.EnvironmentVariables["PROVER_KILL_TIME"] = CommandLineOptions.Clo.ProverKillTime.ToString();
- }
- if (0 <= CommandLineOptions.Clo.SimplifyProverMatchDepth) {
- psi.EnvironmentVariables["PROVER_MATCH_DEPTH"] = CommandLineOptions.Clo.SimplifyProverMatchDepth.ToString();
- }
- if (0 <= CommandLineOptions.Clo.ProverCCLimit) {
- psi.EnvironmentVariables["PROVER_CC_LIMIT"] = CommandLineOptions.Clo.ProverCCLimit.ToString();
- }
- return psi;
- }
-
-
- public override string OptionComments() {
- Contract.Ensures(Contract.Result<string>() != null);
-
- // would we want the timeout stuff here?
- return "";
- }
-
- [NotDelayed]
- // TODO it complains about things not beeing peer consistent upon call to EatPrompt()
- // not sure what is it about... --micmo
- [Verify(false)]
- public SimplifyProverProcess(string proverPath):base(getPSI(proverPath),proverPath)
- //modifies Console.Out.*, Console.Error.*;
- {
- Contract.Requires(proverPath != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- EatPrompt();
- }
-
- private void EatPrompt()
- //modifies this.*;
- //modifies Console.Out.*, Console.Error.*;
- {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- // skips text matching the regular expression: (white space)* ">\t"
- ToFlush();
-
- int ch = 0;
- do {
- ch = FromReadChar();
- } while (Char.IsWhiteSpace((char)ch));
-
- while (ch == 'W') {
- ch = ConsumeWarnings(ch, null);
- }
-
- Expect(ch, ">\t");
- }
-
- public override void AddAxioms(string s) {
- //Contract.Requires(s != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- //ToWriteLine("(PROMPT_OFF)");
- base.AddAxioms(s);
- //ToWriteLine("(PROMPT_ON)");
- EatPrompt();
- }
-
- public override void Feed(string s, int statementCount) {
- //Contract.Requires(s != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- //ToWriteLine("(PROMPT_OFF)");
- base.Feed(s, statementCount);
- //ToWriteLine("(PROMPT_ON)");
- for (int i = 0; i < statementCount; i++) {
- EatPrompt();
- }
- }
-
- public override void PopAxioms() {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- base.PopAxioms();
- EatPrompt();
- }
-
- protected override void DoBeginCheck(string descriptiveName, string formula) {
- //Contract.Requires(descriptiveName != null);
- //Contract.Requires(formula != null);
- //simplify.Refresh();
- //this.Comment("@@@@ Virtual Memory: " + simplify.PeakVirtualMemorySize64);
- //this.Comment("@@@@ Working Set: " + simplify.PeakWorkingSet64);
- //this.Comment("@@@@ Paged Memory: " + simplify.PeakPagedMemorySize64);
-
- ToWriteLine(formula);
- ToFlush();
- }
-
- public override ProverOutcome CheckOutcome(Microsoft.Boogie.ProverInterface.ErrorHandler handler) {
- //Contract.Requires(handler != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- ProverOutcome outcome;
-
- if (this.simplify == null) {
- return ProverOutcome.Inconclusive;
- }
-
- int ch = FromReadChar();
- while (ch == 'W') {
- ch = ConsumeWarnings(ch, handler);
- }
- if (ch == 'E') {
- Expect(ch, "Exceeded PROVER_KILL_TIME -- discontinuing search for counterexamples.");
- FromReadLine();
- ch = FromReadChar();
- if (ch == '\n') {
- ch = FromReadChar();
- }
- Expect(ch, " labels:");
- FromReadLine();
- ch = FromReadChar();
- ch = FromReadChar();
- ch = FromReadChar();
- FromReadLine();
- ch = FromReadChar();
- ch = FromReadChar();
- ch = FromReadChar();
- return ProverOutcome.TimeOut;
- }
- if ('0' <= ch && ch <= '9') {
- // Valid!
- do {
- ch = FromReadChar();
- } while ('0' <= ch && ch <= '9');
- Expect(ch, ": Valid.");
- outcome = ProverOutcome.Valid;
- ToWriteLine(String.Format("; FORMULA {0} IS VALID!", NumFormulasChecked + 1 /*Simplify starts at 1*/));
- } else {
- // now we expect one or more counterexample contexts, each proving a list of labels
- do {
- List<string> labels = ReadLabels(ch);
- handler.OnModel(labels, null);
- ch = FromReadChar();
- } while (ch == 'C');
- // now we expect "<N>: Invalid" where <N> is some number
- while ('0' <= ch && ch <= '9') {
- ch = FromReadChar();
- }
- Expect(ch, ": Invalid.");
- outcome = ProverOutcome.NotValid;
- ToWriteLine(String.Format("; FORMULA {0} IS INVALID", NumFormulasChecked + 1 /*Simplify starts at 1*/));
- }
-
- EatPrompt();
- return outcome;
- }
-
- List<string/*!>!*/> ReadLabels(int ch)
- //modifies this.*;
- {
- Contract.Ensures(Contract.Result<List<string>>() != null);
-
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- Expect(ch, "Counterexample:\n"); // FIX! ? Is there a problem with \r\n here?
- ch = FromReadChar();
- List<string> theLabels;
- if (ch == ' ') {
- // there are labels
- Expect(ch, " labels: ");
- string labels = FromReadLine(); // reads "(A B C ...)\n"
- theLabels = ParseLabels(labels);
- ch = FromReadChar();
- } else {
- theLabels = new List<string>();
- }
- Expect(ch, "\n"); // empty line
-
- return theLabels;
- }
-
- int ConsumeWarnings(int ch, Microsoft.Boogie.ProverInterface.ErrorHandler handler)
- //modifies this.*;
- //modifies Console.Out.*, Console.Error.*;
- {
- Contract.Requires(ch == 'W');
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- Expect(ch, "Warning: ");
- string w = FromReadLine();
- if (w.StartsWith("triggerless quantifier body")) {
- FromReadLine(); // blank line
- w = "triggerless quantifier body: " + FromReadLine(); // expression (body)
- FromReadLine(); // blank line
- FromReadLine(); // "with X pattern variable(s)...
- FromReadLine(); // blank line
- FromReadLine(); // expression (entire quantifier)
- }
-
- if (handler != null)
- handler.OnProverWarning(w);
-
- ch = FromReadChar();
- if (ch == '\n') {
- // make up for a poorly designed ReadLine routine (only the first
- // character of the DOS end-of-line sequence "\r\n" is read)
- ch = FromReadChar();
- }
- return ch;
- }
- }
-
-} \ No newline at end of file
diff --git a/Source/Provers/Simplify/ProverInterface.cs b/Source/Provers/Simplify/ProverInterface.cs
deleted file mode 100644
index 4584b2e7..00000000
--- a/Source/Provers/Simplify/ProverInterface.cs
+++ /dev/null
@@ -1,868 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-using System.IO;
-using System.Text;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.AbstractInterpretation;
-using Microsoft.Boogie.Simplify;
-using Microsoft.Boogie.VCExprAST;
-using Microsoft.Boogie.TypeErasure;
-using System.Text.RegularExpressions;
-
-namespace Microsoft.Boogie.Simplify {
- public abstract class LogProverInterface : ProverInterface {
- [NotDelayed]
- protected LogProverInterface(ProverOptions options,
- string openComment, string closeComment,
- string openActivity, string closeActivity,
- VCExpressionGenerator gen) {
- Contract.Requires(options != null);
- Contract.Requires(openComment != null);
- Contract.Requires(closeComment != null);
- Contract.Requires(openActivity != null);
- Contract.Requires(closeActivity != null);
- Contract.Requires(gen != null);
- Contract.Ensures(this.gen == gen);
- if (options.SeparateLogFiles) {
- this.commonPrefix = new List<string>();
- } else {
- this.logFileWriter = options.OpenLog(null);
- }
- this.openCommentString = openComment;
- this.closeCommentString = closeComment;
- this.openActivityString = openActivity;
- this.closeActivityString = closeActivity;
- this.gen = gen;
- this.options = options;
-
- if (CommandLineOptions.Clo.ShowEnv != CommandLineOptions.ShowEnvironment.Never) {
- // Emit version comment in the log
- LogCommonComment(CommandLineOptions.Clo.Version);
- LogCommonComment(CommandLineOptions.Clo.Environment);
- }
- }
-
- [StrictReadonly]
- [Additive]
- protected readonly VCExpressionGenerator gen;
-
- private TextWriter/*?*/ logFileWriter;
- [StrictReadonly]
- private readonly string openCommentString;
- [StrictReadonly]
- private readonly string closeCommentString;
- [StrictReadonly]
- private readonly string openActivityString;
- [StrictReadonly]
- private readonly string closeActivityString;
- [StrictReadonly]
- protected readonly ProverOptions options;
- [StrictReadonly]
- private readonly List<string>/*?*/ commonPrefix;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(openCommentString != null);
- Contract.Invariant(closeCommentString != null);
- Contract.Invariant(openActivityString != null);
- Contract.Invariant(closeActivityString != null);
- Contract.Invariant(options != null);
- Contract.Invariant(commonPrefix == null || cce.NonNullElements(commonPrefix));
- }
-
-
- public void LogActivity(string s) {
- Contract.Requires(s != null);
- LogActivity(s, false);
- }
-
- public void LogCommon(string s) {
- Contract.Requires(s != null);
- LogActivity(s, true);
- }
-
- private void LogActivity(string s, bool common) {
- Contract.Requires(s != null);
- Contract.Assume(common || !options.SeparateLogFiles || logFileWriter != null);
- if (logFileWriter != null) {
- logFileWriter.Write(openActivityString);
- logFileWriter.Write(s);
- logFileWriter.WriteLine(closeActivityString);
- logFileWriter.Flush();
- }
- if (common && commonPrefix != null) {
- commonPrefix.Add(openActivityString + s + closeActivityString);
- }
- }
-
- /// <summary>
- /// Write "comment" to logfile, if any, formatted as a comment for the theorem prover at hand.
- /// Assumes that "comment" does not contain any characters that would prematurely terminate
- /// the comment (like, perhaps, a newline or "*/").
- /// </summary>
- public override void LogComment(string comment) {
- //Contract.Requires(comment != null);
- LogComment(comment, false);
- }
-
- public void LogCommonComment(string comment) {
- Contract.Requires(comment != null);
- LogComment(comment, true);
- }
-
- private void LogComment(string comment, bool common) {
- Contract.Requires(comment != null);
- Contract.Assume(common || !options.SeparateLogFiles || logFileWriter != null);
- if (logFileWriter != null) {
- logFileWriter.Write(openCommentString);
- logFileWriter.Write(comment);
- logFileWriter.WriteLine(closeCommentString);
- logFileWriter.Flush();
- }
- if (common && commonPrefix != null) {
- commonPrefix.Add(openCommentString + comment + closeCommentString);
- }
- }
-
- public virtual void NewProblem(string descName) {
- Contract.Requires(descName != null);
- if (commonPrefix != null) {
- if (logFileWriter != null) {
- logFileWriter.Close();
- }
- logFileWriter = options.OpenLog(descName);
- if (logFileWriter != null) {
- foreach (string s in commonPrefix) {
- Contract.Assert(s != null);
- logFileWriter.WriteLine(s);
- }
- }
- }
- LogComment("Proof obligation: " + descName);
- }
-
- public override void Close() {
- if (logFileWriter != null) {
- logFileWriter.Close();
- logFileWriter = null;
- }
- }
-
- public override VCExpressionGenerator VCExprGen {
- get {
- Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
- return this.gen;
- }
- }
- }
-
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
- [ContractClass(typeof(ProcessTheoremProverContracts))]
- public abstract class ProcessTheoremProver : LogProverInterface {
- private static string _proverPath;
-
- protected AxiomVCExprTranslator vcExprTranslator {
- get {
- Contract.Ensures(Contract.Result<AxiomVCExprTranslator>() != null);
-
- return cce.NonNull((AxiomVCExprTranslator)ctx.exprTranslator);
- }
- }
-
- protected abstract AxiomVCExprTranslator SpawnVCExprTranslator(ProverOptions p);
-
- // Return the number of axioms pushed to the theorem prover
- protected int FeedNewAxiomsDecls2Prover() {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- if (thmProver == null)
- return 0;
- int ret = 0;
- foreach (string s in vcExprTranslator.NewTypeDecls) {
- Contract.Assert(s != null);
- LogCommon(s);
- thmProver.Feed(s, 0);
- }
- foreach (string s in vcExprTranslator.NewAxioms) {
- Contract.Assert(s != null);
- LogBgPush(s);
- thmProver.AddAxioms(s);
- ret++;
- }
- return ret;
- }
-
- protected static string CodebaseString() {
- Contract.Ensures(Contract.Result<string>() != null);
-
- return Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location));
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(BackgroundPredicates));
- Contract.Invariant(BackgroundPredFilename != null);
- Contract.Invariant(ctx != null);
- }
-
- private static IDictionary<string/*!*/, string/*!>!*/> BackgroundPredicates =
- new Dictionary<string/*!*/, string/*!*/>();
-
- protected static string GetBackgroundPredicate(string filename) {
- Contract.Requires(filename != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- string res;
- if (!BackgroundPredicates.TryGetValue(filename, out res)) {
- // do we have to lock/synchronise anything?
- string univBackPredPath = Path.Combine(CodebaseString(), filename);
- using (StreamReader reader = new System.IO.StreamReader(univBackPredPath)) {
- res = reader.ReadToEnd();
- }
- BackgroundPredicates.Add(filename, res);
- }
- return cce.NonNull(res);
- }
-
- static void InitializeGlobalInformation(string proverExe)
- // throws ProverException, System.IO.FileNotFoundException;
- {
- Contract.Requires(proverExe != null);
- Contract.Ensures(_proverPath != null);
-
- if (CommandLineOptions.Clo.Z3ExecutablePath != null) {
- _proverPath = CommandLineOptions.Clo.Z3ExecutablePath;
- }
-
- if (_proverPath == null) {
- // Initialize '_proverPath'
- _proverPath = Path.Combine(CodebaseString(), proverExe);
- string firstTry = _proverPath;
-
- if (File.Exists(firstTry))
- return;
-
- string programFiles = Environment.GetEnvironmentVariable("ProgramFiles");
- Contract.Assert(programFiles != null);
- string programFilesX86 = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
- if (programFiles.Equals(programFilesX86)) {
- // If both %ProgramFiles% and %ProgramFiles(x86)% point to "ProgramFiles (x86)", use %ProgramW6432% instead.
- programFiles = Environment.GetEnvironmentVariable("ProgramW6432");
- }
-
-
- List<string> z3Dirs = new List<string>();
- if (Directory.Exists(programFiles + @"\Microsoft Research\")) {
- string msrDir = programFiles + @"\Microsoft Research\";
- z3Dirs.AddRange(Directory.GetDirectories(msrDir, "Z3-*"));
- }
- if (Directory.Exists(programFilesX86 + @"\Microsoft Research\")) {
- string msrDir = programFilesX86 + @"\Microsoft Research\";
- z3Dirs.AddRange(Directory.GetDirectories(msrDir, "Z3-*"));
- }
-
- // Look for the most recent version of Z3.
- int minor = 0, major = 0;
- string winner = null;
- Regex r = new Regex(@"^Z3-(\d+)\.(\d+)$");
- foreach (string d in z3Dirs) {
- string name = new DirectoryInfo(d).Name;
- foreach (Match m in r.Matches(name)) {
- int ma, mi;
- ma = int.Parse(m.Groups[1].ToString());
- mi = int.Parse(m.Groups[2].ToString());
- if (major < ma || (major == ma && minor < mi)) {
- major = ma;
- minor = mi;
- winner = d;
- }
- }
- }
-
- if (major == 0 && minor == 0) {
- throw new ProverException("Cannot find executable: " + firstTry);
- }
- Contract.Assert(winner != null);
-
- _proverPath = Path.Combine(Path.Combine(winner, "bin"), proverExe);
- if (!File.Exists(_proverPath)) {
- throw new ProverException("Cannot find prover: " + _proverPath);
- }
-
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("[TRACE] Using prover: " + _proverPath);
- }
- }
- }
-
- [Rep]
- protected internal ProverProcess thmProver;
- bool currentProverHasBeenABadBoy = false;
- // invariant currentProverHasBeenABadBoy ==> thmProver != null;
- protected int restarts = 0;
- protected DeclFreeProverContext ctx;
- protected string BackgroundPredFilename;
- protected ConsoleCancelEventHandler cancelEvent;
-
- [NotDelayed]
- public ProcessTheoremProver(ProverOptions options, VCExpressionGenerator gen, DeclFreeProverContext ctx,
- string proverExe, string backgroundPred)
- : base(options, "; ", "", "", "", gen) {
- Contract.Requires(options != null);
- Contract.Requires(gen != null);
- Contract.Requires(ctx != null);
- Contract.Requires(proverExe != null);
- Contract.Requires(backgroundPred != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- BackgroundPredFilename = backgroundPred;
- InitializeGlobalInformation(proverExe);
- this.ctx = ctx;
-
-
- // ensure that a VCExprTranslator is available
- // if none exists so far, we have to create a new one
- // from scratch and feed the axioms to it
- if (ctx.exprTranslator == null) {
- AxiomVCExprTranslator tl = SpawnVCExprTranslator(options);
- ctx.exprTranslator = tl;
- tl.AddAxiom(tl.translate(ctx.Axioms, -1));
- // we clear the lists with new axioms and declarations;
- // they are not needed at this point
- List<string> x = tl.NewAxioms;
- //x = x; // make the compiler happy: somebody uses the value of x
- x = tl.NewTypeDecls;
- }
- }
-
- /// <summary>
- /// MSchaef: Allows to Push a VCExpression as Axiom on the prover stack (beta)
- /// </summary>
- public override void PushVCExpression(VCExpr vc) {
- //Contract.Requires(vc != null);
- vcExprTranslator.AddAxiom(vcExprTranslator.translate(vc, 1));
- }
-
- public override string VCExpressionToString(VCExpr vc) {
- //Contract.Requires(vc != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- return vcExprTranslator.translate(vc, 1);
- }
-
- // Number of axioms pushed since the last call to Check
- public override int NumAxiomsPushed() {
- return vcExprTranslator.NewAxiomsCount;
- }
-
- // Feed the axioms pushed since the last call to Check to the theorem prover
- public override int FlushAxiomsToTheoremProver() {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- return FeedNewAxiomsDecls2Prover();
- }
-
- public override void Pop() {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- Contract.Assert(thmProver != null);
- LogCommon("(BG_POP)");
- thmProver.PopAxioms();
- }
-
- [NoDefaultContract] // important, since we have no idea what state the object might be in when this handler is invoked
- void ControlCHandler(object o, ConsoleCancelEventArgs a) {
- if (thmProver != null) {
- thmProver.Kill();
- }
- }
-
- public override void Close() {
- if (cancelEvent != null) {
- Console.CancelKeyPress -= cancelEvent;
- cancelEvent = null;
- }
- if (thmProver != null) {
- cce.BeginExpose(this);
- {
- thmProver.Close();
- thmProver = null;
- currentProverHasBeenABadBoy = false;
- }
- cce.EndExpose();
- }
- base.Close();
- }
-
- private UnexpectedProverOutputException proverException;
-
- public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler) {
- //Contract.Requires(descriptiveName != null);
- //Contract.Requires(vc != null);
- //Contract.Requires(handler != null);
- this.NewProblem(descriptiveName);
- this.proverException = null;
-
- try {
- this.ResurrectProver();
-
- string vcString = vcExprTranslator.translate(vc, 1);
-
- Helpers.ExtraTraceInformation("Sending data to theorem prover");
-
- int num_axioms_pushed =
- FeedNewAxiomsDecls2Prover();
-
- LogActivity(vcString);
-
- Contract.Assert(thmProver != null);
- thmProver.BeginCheck(descriptiveName, vcString);
-
- if (CommandLineOptions.Clo.StratifiedInlining > 0) {
- // Pop all the axioms that were pushed by FeedNewAxiomsDecls2Prover
- for (int i = 0; i < num_axioms_pushed; i++) {
- LogBgPop();
- thmProver.PopAxioms();
- }
- }
-
- if (CommandLineOptions.Clo.RestartProverPerVC) {
- LogComment("Will restart the prover due to /restartProver option");
- currentProverHasBeenABadBoy = true;
- }
- } catch (UnexpectedProverOutputException e) {
- proverException = e;
- }
- }
-
- public override Outcome CheckOutcome(ErrorHandler handler) {
- //Contract.Requires(handler != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- if (this.thmProver == null) {
- return Outcome.Undetermined;
- }
-
- if (proverException == null) {
- try {
- ProverProcess.ProverOutcome result = thmProver.CheckOutcome(handler);
-
- if (options.ForceLogStatus) {
- switch (result) {
- case ProverProcess.ProverOutcome.Valid:
- LogActivity("DBG_WAS_VALID");
- break;
- case ProverProcess.ProverOutcome.NotValid:
- LogActivity("DBG_WAS_INVALID");
- break;
- }
- }
-
- switch (result) {
- case ProverProcess.ProverOutcome.Valid:
- return Outcome.Valid;
- case ProverProcess.ProverOutcome.TimeOut:
- return Outcome.TimeOut;
- case ProverProcess.ProverOutcome.OutOfMemory:
- return Outcome.OutOfMemory;
- case ProverProcess.ProverOutcome.Inconclusive:
- return Outcome.Undetermined;
- case ProverProcess.ProverOutcome.NotValid:
- return Outcome.Invalid;
- }
- } catch (UnexpectedProverOutputException e) {
- proverException = e;
- }
- }
-
- Contract.Assume(proverException != null);
- LogComment("***** Unexpected prover output");
- cce.BeginExpose(this);
- {
- currentProverHasBeenABadBoy = true; // this will cause the next resurrect to restart the prover
- }
- cce.EndExpose();
- throw proverException;
- }
-
- protected virtual void ResurrectProver() {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- cce.BeginExpose(this);
- {
- if (thmProver != null) {
- if (thmProver.HasExited) {
- DateTime now = DateTime.Now;
- LogComment("***** Prover Crashed at or before " + now.ToString("G"));
-
- } else if (CommandLineOptions.Clo.MaxProverMemory > 0 &&
- thmProver.NumFormulasChecked > CommandLineOptions.Clo.MinNumOfProverCalls &&
- thmProver.PeakVirtualMemorySize > CommandLineOptions.Clo.MaxProverMemory) {
- LogComment("***** Exceeded memory limit. Peak memory usage so far: " +
- thmProver.PeakVirtualMemorySize / CommandLineOptions.Megabyte + "MB");
-
- } else if (!currentProverHasBeenABadBoy) {
- // prover is ready to go
- return;
- }
-
- thmProver.Close();
- thmProver = null;
- currentProverHasBeenABadBoy = false;
- restarts++;
-
- if (CommandLineOptions.Clo.StratifiedInlining > 0)
- {
- Console.WriteLine("Warning: restarting theorem prover. Context could be lost");
- }
- }
-
- FireUpNewProver();
- }
- cce.EndExpose();
- }
-
- protected abstract ProverProcess CreateProverProcess(string proverPath);
-
- public void LogBgPush(string s) {
- Contract.Requires(s != null);
- LogCommon("(BG_PUSH ");
- LogCommon(s);
- LogCommon(")");
- }
-
- public void LogBgPop() {
- LogCommon("(BG_POP)");
- }
-
- [NoDefaultContract]
- private void FireUpNewProver()
- {
- Contract.Requires( cce.IsExposed(this));
- Contract.Requires( thmProver == null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- if (cancelEvent == null && CommandLineOptions.Clo.RunningBoogieFromCommandLine) {
- cancelEvent = new ConsoleCancelEventHandler(ControlCHandler);
- Console.CancelKeyPress += cancelEvent;
- }
- thmProver = CreateProverProcess(_proverPath);
- if (restarts == 0) {
- foreach (string s in thmProver.OptionComments().Split('\n')) {Contract.Assert(s != null);
- LogCommonComment(s);
- }
- foreach (string parmsetting in thmProver.ParameterSettings) {Contract.Assert(parmsetting != null);
- LogCommon(parmsetting);
- }
- }
- foreach (string parmsetting in thmProver.ParameterSettings) {Contract.Assert(parmsetting != null);
- thmProver.Feed(parmsetting, 0);
- }
- thmProver.Feed(GetBackgroundPredicate(BackgroundPredFilename), 3);
-
- if (restarts == 0) {
- // log the stuff before feeding it into the prover, so when it dies
- // and takes Boogie with it, we know what happened
- LogCommon(GetBackgroundPredicate(BackgroundPredFilename));
-
- foreach (string s in vcExprTranslator.AllTypeDecls){Contract.Assert(s != null);
- LogCommon(s);}
- foreach (string s in vcExprTranslator.AllAxioms){Contract.Assert(s != null);
- LogBgPush(s);}
-
- LogCommonComment("Initialized all axioms.");
- }
-
- foreach (string s in vcExprTranslator.AllTypeDecls){Contract.Assert(s != null);
- thmProver.Feed(s, 0);}
- foreach (string s in vcExprTranslator.AllAxioms){Contract.Assert(s != null);
- thmProver.AddAxioms(s);}
-
- // we have sent everything to the prover and can clear the lists with
- // new axioms and declarations
- List<string> x = vcExprTranslator.NewAxioms;
- //x = x; // make the compiler happy: somebody uses the value of x
- x = vcExprTranslator.NewTypeDecls;
- }
-
- public override ProverContext Context {
- get {
- Contract.Ensures(Contract.Result<ProverContext>() != null);
- return this.ctx;
- }
- }
- }
- [ContractClassFor(typeof(ProcessTheoremProver))]
- public abstract class ProcessTheoremProverContracts :ProcessTheoremProver{
- protected override AxiomVCExprTranslator SpawnVCExprTranslator(ProverOptions p) {
- Contract.Requires(p != null);
- Contract.Ensures(Contract.Result<AxiomVCExprTranslator>() != null);
- throw new NotImplementedException();
-
- }
- protected override ProverProcess CreateProverProcess(string proverPath) {
- Contract.Requires(proverPath != null);
- Contract.Ensures(Contract.Result<ProverProcess>() != null);
- throw new NotImplementedException();
- }
- [NotDelayed]
- public ProcessTheoremProverContracts(ProverOptions options, VCExpressionGenerator gen, DeclFreeProverContext ctx,
- string proverExe, string backgroundPred):base(options,gen,ctx,proverExe,backgroundPred)
- {throw new NotImplementedException();}
- }
-
- public class SimplifyTheoremProver : ProcessTheoremProver {
- [NotDelayed]
- public SimplifyTheoremProver(ProverOptions options, VCExpressionGenerator gen, DeclFreeProverContext ctx)
- : base(options, gen, ctx, "simplify.exe", "UnivBackPred2.sx") {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- }
-
- protected override ProverProcess CreateProverProcess(string proverPath) {
- //Contract.Requires(proverPath != null);
- Contract.Ensures(Contract.Result<ProverProcess>() != null);
-
- return new SimplifyProverProcess(proverPath);
- }
-
- protected override AxiomVCExprTranslator SpawnVCExprTranslator(ProverOptions opts) {
- //Contract.Requires(opts!=null);
- Contract.Ensures(Contract.Result<AxiomVCExprTranslator>() != null);
-
- return new SimplifyVCExprTranslator(gen);
- }
- }
-
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
-
- public abstract class AxiomVCExprTranslator : VCExprTranslator {
- protected AxiomVCExprTranslator() {
- AllAxioms = new List<string> ();
- NewAxiomsAttr = new List<string> ();
- AllTypeDecls = new List<string> ();
- NewTypeDeclsAttr = new List<string> ();
- }
-
- protected AxiomVCExprTranslator(AxiomVCExprTranslator tl) {
- Contract.Requires(tl != null);
- AllAxioms = new List<string>(tl.AllAxioms);
- NewAxiomsAttr = new List<string>(tl.NewAxiomsAttr);
- AllTypeDecls = new List<string>(tl.AllTypeDecls);
- NewTypeDeclsAttr = new List<string>(tl.NewTypeDeclsAttr);
- }
-
- // we store all typing-related axioms that have been sent to the prover
- // so that the prover can be re-initialised in case it dies
- public readonly List<string/*!>!*/> AllAxioms;
- private List<string/*!>!*/> NewAxiomsAttr;
-
- // The length of the list NewAxiomsAttr
- public int NewAxiomsCount {
- get {
- return NewAxiomsAttr.Count;
- }
- }
-
- public List<string/*!>!*/> NewAxioms {
- get {
- Contract.Ensures(Contract.Result<List<string>>() != null);
-
- List<string/*!>!*/> res = NewAxiomsAttr;
- NewAxiomsAttr = new List<string>();
- return res;
- }
- }
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AllAxioms != null);
- Contract.Invariant(NewAxiomsAttr != null);
- Contract.Invariant(AllTypeDecls != null);
- Contract.Invariant(NewTypeDeclsAttr != null);
- }
-
-
- // similarly, a list of declarations that have been sent to the prover
- public readonly List<string/*!>!*/> AllTypeDecls;
- private List<string/*!>!*/> NewTypeDeclsAttr;
-
- public List<string>/*!>!*/ NewTypeDecls {
- get {
- List<string/*!>!*/> res = NewTypeDeclsAttr;
- NewTypeDeclsAttr = new List<string/*!*/>();
- return res;
- }
- }
-
- public void AddAxiom(string axiom) {
- Contract.Requires(axiom != null);
- AllAxioms.Add(axiom);
- NewAxiomsAttr.Add(axiom);
- }
-
- public void AddTypeDecl(string typeDecl) {
- Contract.Requires(typeDecl != null);
- AllTypeDecls.Add(typeDecl);
- NewTypeDeclsAttr.Add(typeDecl);
- }
- }
-
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
-
- public class SimplifyVCExprTranslator : AxiomVCExprTranslator {
- public SimplifyVCExprTranslator(VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Gen = gen;
- TypeAxiomBuilder axBuilder;
- switch (CommandLineOptions.Clo.TypeEncodingMethod) {
- case CommandLineOptions.TypeEncoding.Arguments:
- axBuilder = new TypeAxiomBuilderArguments(gen);
- break;
- default:
- axBuilder = new TypeAxiomBuilderPremisses(gen);
- break;
- }
- axBuilder.Setup();
- AxBuilder = axBuilder;
- Namer = new UniqueNamer();
- LitAbstracter = new BigLiteralAbstracter(gen);
- }
-
- private SimplifyVCExprTranslator(SimplifyVCExprTranslator tl)
- : base(tl) {
- Contract.Requires(tl != null);
- Gen = tl.Gen;
- AxBuilder = (TypeAxiomBuilder)tl.AxBuilder.Clone();
- Namer = (UniqueNamer)tl.Namer.Clone();
- LitAbstracter = (BigLiteralAbstracter)tl.LitAbstracter.Clone();
- }
-
- public override Object Clone() {
- Contract.Ensures(Contract.Result<object>() != null);
-
- return new SimplifyVCExprTranslator(this);
- }
-
- private readonly VCExpressionGenerator Gen;
- private readonly TypeAxiomBuilder AxBuilder;
- private readonly UniqueNamer Namer;
- private readonly BigLiteralAbstracter LitAbstracter;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Gen != null);
- Contract.Invariant(AxBuilder != null);
- Contract.Invariant(Namer != null);
- Contract.Invariant(LitAbstracter != null);
- }
-
-
- public override string Lookup(VCExprVar var) {
- //Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- VCExprVar v = AxBuilder.TryTyped2Untyped(var);
- if (v != null) {
- var = v;
- }
- return Namer.Lookup(var);
- }
-
- public override string translate(VCExpr expr, int polarity) {
- //Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- Let2ImpliesMutator letImplier = new Let2ImpliesMutator(Gen);
- Contract.Assert(letImplier != null);
-
- // handle the types in the VCExpr
- TypeEraser eraser;
- switch (CommandLineOptions.Clo.TypeEncodingMethod) {
- case CommandLineOptions.TypeEncoding.Arguments:
- eraser = new TypeEraserArguments((TypeAxiomBuilderArguments)AxBuilder, Gen);
- break;
- case CommandLineOptions.TypeEncoding.Monomorphic:
- eraser = null;
- break;
- default:
- eraser = new TypeEraserPremisses((TypeAxiomBuilderPremisses)AxBuilder, Gen);
- break;
- }
- VCExpr exprWithoutTypes = eraser != null ? eraser.Erase(expr, polarity) : expr;
- Contract.Assert(exprWithoutTypes != null);
-
- TermFormulaFlattener flattener = new TermFormulaFlattener(Gen);
- Contract.Assert(flattener != null);
- VCExpr exprWithLet = flattener.Flatten(exprWithoutTypes);
- Contract.Assert(exprWithLet != null);
- VCExpr exprWithoutLet = letImplier.Mutate(exprWithLet);
- Contract.Assert(exprWithoutLet != null);
-
- // big integer literals
- VCExpr exprWithoutBigLits = LitAbstracter.Abstract(exprWithoutLet);
- Contract.Assert(exprWithoutBigLits != null);
- AddAxiom(SimplifyLikeExprLineariser.ToSimplifyString(LitAbstracter.GetNewAxioms(),
- Namer));
-
- // type axioms
- VCExpr axiomsWithLet = flattener.Flatten(AxBuilder.GetNewAxioms());
- Contract.Assert(axiomsWithLet != null);
- VCExpr axiomsWithoutLet = letImplier.Mutate(axiomsWithLet);
- Contract.Assert(axiomsWithoutLet != null);
-
- AddAxiom(SimplifyLikeExprLineariser.ToSimplifyString(axiomsWithoutLet, Namer));
- return SimplifyLikeExprLineariser.ToSimplifyString(exprWithoutBigLits, Namer);
- }
- }
-
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
-
- public class Factory : ProverFactory {
- public override object SpawnProver(ProverOptions options, object ctxt) {
- //Contract.Requires(options != null);
- //Contract.Requires(ctxt != null);
- Contract.Ensures(Contract.Result<object>() != null);
-
- return new SimplifyTheoremProver(options,
- cce.NonNull((DeclFreeProverContext)ctxt).ExprGen,
- cce.NonNull((DeclFreeProverContext)ctxt));
- }
-
- public override object NewProverContext(ProverOptions options) {
- //Contract.Requires(options != null);
- Contract.Ensures(Contract.Result<object>() != null);
-
- if (CommandLineOptions.Clo.BracketIdsInVC < 0) {
- CommandLineOptions.Clo.BracketIdsInVC = 1;
- }
- VCExpressionGenerator gen = new VCExpressionGenerator();
- Contract.Assert(gen != null);
- List<string>/*!>!*/ proverCommands = new List<string> ();
- Contract.Assert(cce.NonNullElements(proverCommands));
- proverCommands.Add("simplify");
- return new DeclFreeProverContext(gen, new VCGenerationOptions(proverCommands));
- }
-
- public override CommandLineOptions.VCVariety DefaultVCVariety {
- get {
- return CommandLineOptions.VCVariety.BlockNested;
- }
- }
-
- // needed to make test7 pass
- public override bool SupportsDags {
- get {
- return true;
- }
- }
- }
-}
diff --git a/Source/Provers/Simplify/Simplify.csproj b/Source/Provers/Simplify/Simplify.csproj
deleted file mode 100644
index 81d2f90a..00000000
--- a/Source/Provers/Simplify/Simplify.csproj
+++ /dev/null
@@ -1,210 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{FEE9F01B-9722-4A76-A24B-72A4016DFA8E}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Microsoft.Boogie.Simplify</RootNamespace>
- <AssemblyName>Provers.Simplify</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile>Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for Simplify.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\Provers.Simplify.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Let2ImpliesVisitor.cs" />
- <Compile Include="Prover.cs" />
- <Compile Include="ProverInterface.cs" />
- <Compile Include="..\..\version.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Graph\Graph.csproj">
- <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCExpr\VCExpr.csproj">
- <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
- <Name>VCExpr</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project> \ No newline at end of file
diff --git a/Source/Provers/Simplify/cce.cs b/Source/Provers/Simplify/cce.cs
deleted file mode 100644
index ef594484..00000000
--- a/Source/Provers/Simplify/cce.cs
+++ /dev/null
@@ -1,193 +0,0 @@
-using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
- }
- //[Pure]
- //public static bool NonNullElements(VariableSeq collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
-} \ No newline at end of file
diff --git a/Source/Provers/Z3/Inspector.cs b/Source/Provers/Z3/Inspector.cs
deleted file mode 100644
index c9bdfa31..00000000
--- a/Source/Provers/Z3/Inspector.cs
+++ /dev/null
@@ -1,162 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.IO;
-using System.Diagnostics;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-//using util;
-using Microsoft.Boogie;
-using Microsoft.Boogie.Simplify;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.Z3
-{
- internal class FindLabelsVisitor : TraversingVCExprVisitor<bool, bool> {
- public HashSet<string/*!*/>/*!*/ Labels = new HashSet<string/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNull(Labels));
- }
-
-
- public static HashSet<string/*!*/>/*!*/ FindLabels(VCExpr/*!*/ expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(cce.NonNull(Contract.Result<HashSet<string/*!*/>/*!*/>()));
-
- FindLabelsVisitor visitor = new FindLabelsVisitor();
- visitor.Traverse(expr, true);
- return visitor.Labels;
- }
-
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node!=null);
- VCExprNAry nary = node as VCExprNAry;
- if (nary != null) {
- VCExprLabelOp lab = nary.Op as VCExprLabelOp;
- if (lab != null) {
- Labels.Add(lab.label);
- }
- }
- return true;
- }
- }
-
- internal class Inspector {
- [Rep] protected readonly Process inspector;
- [Rep] readonly TextReader fromInspector;
- [Rep] readonly TextWriter toInspector;
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(inspector!=null);
- Contract.Invariant(fromInspector!=null);
- Contract.Invariant(toInspector != null);
- }
-
-
- public Inspector(Z3InstanceOptions opts)
- {
- Contract.Requires(opts != null);
- ProcessStartInfo psi = new ProcessStartInfo(opts.Inspector);
- Contract.Assert(psi!=null);
- psi.CreateNoWindow = true;
- psi.UseShellExecute = false;
- psi.RedirectStandardInput = true;
- psi.RedirectStandardOutput = true;
- psi.RedirectStandardError = false;
-
- try
- {
- Process inspector = Process.Start(psi);
- this.inspector = inspector;
- fromInspector = inspector.StandardOutput;
- toInspector = inspector.StandardInput;
- }
- catch (System.ComponentModel.Win32Exception e)
- {
- throw new Exception(string.Format("Unable to start the inspector process {0}: {1}", opts.Inspector, e.Message));
- }
- }
-
- public void NewProver()
- {
- }
-
- public void NewProblem(string descriptiveName, VCExpr vc, ProverInterface.ErrorHandler handler)
- {
- Contract.Requires(descriptiveName != null);
- Contract.Requires(vc != null);
- Contract.Requires(handler != null);
- HashSet<string/*!*/>/*!*/ labels = FindLabelsVisitor.FindLabels(vc);
- Contract.Assert(labels!=null);
- toInspector.WriteLine("PROBLEM " + descriptiveName);
- toInspector.WriteLine("TOKEN BEGIN");
- foreach (string lab in labels) {
- Contract.Assert(lab!=null);
- string no = lab.Substring(1);
- Absy absy = handler.Label2Absy(no);
-
- IToken tok = absy.tok;
- AssertCmd assrt = absy as AssertCmd;
- Block blk = absy as Block;
- string val = tok.val; // might require computation, so cache it
- if (val == "foo" || tok.filename == null) continue; // no token
-
- toInspector.Write("TOKEN ");
- toInspector.Write(lab);
- toInspector.Write(" ");
-
- if (assrt != null) {
- toInspector.Write("ASSERT");
- string errData = assrt.ErrorData as string;
- if (errData != null) {
- val = errData;
- } else if (assrt.ErrorMessage != null) {
- val = assrt.ErrorMessage;
- }
- } else if (blk != null) {
- toInspector.Write("BLOCK ");
- toInspector.Write(blk.Label);
- } else {
- Contract.Assume( false);
- }
- if (val == null || val == "assert" || val == "ensures") { val = ""; }
-
- if (absy is LoopInitAssertCmd) {
- val += " (loop entry)";
- } else if (absy is LoopInvMaintainedAssertCmd) {
- val += " (loop body)";
- } else if (val.IndexOf("#VCCERR") >= 0) {
- // skip further transformations
- } else if (absy is AssertRequiresCmd) {
- AssertRequiresCmd req = (AssertRequiresCmd)absy;
- IToken t2 = req.Requires.tok;
- string tval = t2.val;
- if (tval == "requires")
- tval = string.Format("{0}({1},{2}))", t2.filename, t2.line, t2.col);
- string call = "";
- if (val != "call") call = " in call to " + val;
- val = string.Format("precondition {0}{1}", tval, call);
- }
-
- val = val.Replace("\r", "").Replace("\n", " ");
-
- toInspector.WriteLine(string.Format(" {0} {1} :@:{2}:@:{3}", tok.line, tok.col, tok.filename, val));
- }
- toInspector.WriteLine("TOKEN END");
- }
-
- public void StatsLine(string line)
- {
- Contract.Requires(line != null);
- toInspector.WriteLine(line);
- toInspector.Flush();
- }
- }
-}
diff --git a/Source/Provers/Z3/Prover.cs b/Source/Provers/Z3/Prover.cs
deleted file mode 100644
index 6a066f1f..00000000
--- a/Source/Provers/Z3/Prover.cs
+++ /dev/null
@@ -1,937 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-// #define RECENT_Z3 // 2.20 or newer
-
-using System;
-using System.IO;
-using System.Diagnostics;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using util;
-using Microsoft.Boogie;
-using Microsoft.Boogie.Simplify;
-using Microsoft.Basetypes;
-
-// Simplified interface to an external prover like Simplify or the z3 process, taken from Bird.
-namespace Microsoft.Boogie.Z3
-{
- internal class Z3ProverProcess : ProverProcess
- {
- [Peer]
- private Z3InstanceOptions opts;
- [Peer]
- private readonly Inspector/*?*/ inspector;
- private readonly bool expectingModel = false;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(opts != null);
- Contract.Invariant(cce.NonNullElements(parameterSettings));
- }
-
- class OptionValue
- {
- public readonly string Option;
- public readonly string Value;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Option != null);
- Contract.Invariant(Value != null);
- }
-
- public OptionValue(string option, string value) { Contract.Requires(option != null); Contract.Requires(value != null); Option = option; Value = value; }
- }
-
- static void AddOption(List<OptionValue> parms, string option, string value)
- //modifies parms.*; TODO:
- {
- Contract.Requires(option != null);
- Contract.Requires(value != null);
- Contract.Requires(cce.NonNullElements(parms));
- OptionValue ov = new OptionValue(option, value);
- cce.Owner.AssignSame(ov, cce.Owner.ElementProxy(parms));
- parms.Add(ov);
- }
-
- private List<OptionValue/*!>!*/> parameterSettings;
-
- static void AppendCmdLineOption(StringBuilder cmdLineBldr, string name, object value) {
- cmdLineBldr.Append(' ').Append(OptionChar()).Append(name).Append(':').Append(value);
- }
-
- static void AppendCmdLineOption(StringBuilder cmdLineBldr, string name) {
- cmdLineBldr.Append(' ').Append(OptionChar()).Append(name);
- }
-
- static bool ExpectingModel()
- {
- return CommandLineOptions.Clo.PrintErrorModel >= 1 ||
- CommandLineOptions.Clo.EnhancedErrorMessages == 1 ||
- CommandLineOptions.Clo.ModelViewFile != null ||
- CommandLineOptions.Clo.ContractInfer ||
- CommandLineOptions.Clo.LazyInlining > 0 ||
- CommandLineOptions.Clo.StratifiedInlining > 0;
- }
-
- static string/*!*/ CreateCommandLineArgsForOptions(Z3InstanceOptions opts)
- {
- StringBuilder cmdLineArgsBldr = new StringBuilder();
- AppendCmdLineOption(cmdLineArgsBldr, "si");
-
- if (CommandLineOptions.Clo.z3AtFlag)
- AppendCmdLineOption(cmdLineArgsBldr, "@");
-
- if (0 <= CommandLineOptions.Clo.ProverCCLimit)
- AppendCmdLineOption(cmdLineArgsBldr, "cex", CommandLineOptions.Clo.ProverCCLimit);
-
- if (0 <= opts.Timeout)
- AppendCmdLineOption(cmdLineArgsBldr, "t", opts.Timeout);
-
- if (ExpectingModel())
- AppendCmdLineOption(cmdLineArgsBldr, "m");
-
- foreach (string opt in CommandLineOptions.Clo.Z3Options) {
- Contract.Assert(opt != null);
- cmdLineArgsBldr.Append(" \"").Append(opt).Append('\"');
- }
-
- return cmdLineArgsBldr.ToString();
- }
-
- static List<OptionValue/*!*/>/*!*/ CreateParameterListForOptions(Z3InstanceOptions opts, Inspector inspector)
- {
- List<OptionValue/*!*/>/*!*/ result = new List<OptionValue/*!*/>();
-
- AddOption(result, "MODEL_PARTIAL", "true");
-
- AddOption(result, "MODEL_HIDE_UNUSED_PARTITIONS", "false");
- AddOption(result, "MODEL_V1", "true");
- AddOption(result, "ASYNC_COMMANDS", "false");
-
-#if RECENT_Z3
- AddOption(result, "AUTO_CONFIG", "false");
- AddOption(result, "MBQI", "false");
-#else
- AddOption(result, "MODEL_VALUE_COMPLETION", "false");
-#endif
-
- if (!opts.OptimizeForBv) {
- // Phase selection means to always try the negative literal polarity first, seems to be good for Boogie.
- // The restart parameters change the restart behavior to match Z3 v1, which also seems to be good.
- AddOption(result, "PHASE_SELECTION", "0");
- AddOption(result, "RESTART_STRATEGY", "0");
- AddOption(result, "RESTART_FACTOR", "|1.5|");
-
- // Make the integer model more diverse by default, speeds up some benchmarks a lot.
- AddOption(result, "ARITH_RANDOM_INITIAL_VALUE", "true");
-
- // The left-to-right structural case-splitting strategy.
-#if !RECENT_Z3
- AddOption(result, "SORT_AND_OR", "false");
-#endif
- AddOption(result, "CASE_SPLIT", "3");
-
- // In addition delay adding unit conflicts.
- AddOption(result, "DELAY_UNITS", "true");
- AddOption(result, "DELAY_UNITS_THRESHOLD", "16");
- }
-
- // This is used by VCC, but could be also useful for others, if sk_hack(foo(x)) is included as trigger,
- // the foo(x0) will be activated for e-matching when x is skolemized to x0.
- AddOption(result, "NNF_SK_HACK", "true");
-
- // More or less like MAM=0.
- AddOption(result, "QI_EAGER_THRESHOLD", "100");
- // Complex proof attempts in VCC (and likely elsewhere) require matching depth of 20 or more.
-
- // the following will make the :weight option more usable
- AddOption(result, "QI_COST", "|\"(+ weight generation)\"|");
-
- if (opts.Inspector != null)
- AddOption(result, "PROGRESS_SAMPLING_FREQ", "100");
-
- AddOption(result, "TYPE_CHECK", "true");
- AddOption(result, "BV_REFLECT", "true");
-
- foreach (string opt in CommandLineOptions.Clo.Z3Options) {
- Contract.Assert(opt != null);
- int eq = opt.IndexOf("=");
- // we add them both to command line and the input file:
- // - allow for overriding default options
- // - some options (like TRACE) work only from command line
- // Also options with spaces do not work with (SETPARAMETER ...)
- if (eq > 0 && opt.IndexOf(" ") < 0 && 'A' <= opt[0] && opt[0] <= 'Z') {
- AddOption(result, opt.Substring(0, eq), opt.Substring(eq + 1));
- }
- }
-
- return result;
- }
-
- //[NotDelayed]
- [Captured]
- public Z3ProverProcess(Z3InstanceOptions opts, Inspector inspector)
- : base(ComputeProcessStartInfo(opts), opts.ExeName) { // throws ProverException
- Contract.Requires(opts != null);
- Contract.Requires(inspector == null || cce.Owner.Same(opts, inspector));
- this.parameterSettings = CreateParameterListForOptions(opts, inspector);
- cce.Owner.AssignSame(this, opts);
- this.opts = opts;
- this.inspector = inspector;
- this.expectingModel = ExpectingModel();
- }
-
- private static ProcessStartInfo ComputeProcessStartInfo(Z3InstanceOptions opts)
- {
- return new ProcessStartInfo(opts.ExeName, CreateCommandLineArgsForOptions(opts))
- {
- CreateNoWindow = true,
- UseShellExecute = false,
- RedirectStandardInput = true,
- RedirectStandardOutput = true,
- RedirectStandardError = true
- };
- }
-
- public override string OptionComments() {
- Contract.Ensures(Contract.Result<string>() != null);
-
- StringBuilder sb = new StringBuilder();
- sb.AppendFormat("Z3 command line: {0} {1}\nUser supplied Z3 options:",
- opts.ExeName, this.simplify.StartInfo.Arguments);
- Contract.Assume(cce.IsPeerConsistent(CommandLineOptions.Clo));
- foreach (string opt in CommandLineOptions.Clo.Z3Options) {
- Contract.Assert(opt != null);
- sb.Append(" ").Append(opt);
- }
- sb.AppendFormat("\nProver options: {0}\n", opts.ToString());
- return sb.ToString();
- }
-
- //[Pure(false)]
- public override IEnumerable<string/*!>!*/> ParameterSettings {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<string>>()));
- foreach (OptionValue opt in parameterSettings) {
- yield return "(SETPARAMETER " + opt.Option + " " + opt.Value + ")";
- }
- }
- }
-
- // z3 uses different magic characters for options on linux/unix and on windows
- private static string OptionChar() {
- Contract.Ensures(Contract.Result<string>() != null);
-
- Contract.Assume(Environment.OSVersion != null);
- switch (Environment.OSVersion.Platform) {
- case PlatformID.Unix:
- return "-";
- default:
- return "/";
- }
- }
-
- protected override void DoBeginCheck(string descriptiveName, string formula) {
- //Contract.Requires(descriptiveName != null);
- //Contract.Requires(formula != null);
- ToWriteLine(formula);
- ToWriteLine(String.Format("; END OF FORMULA {0} - {1}", NumFormulasChecked.ToString(), descriptiveName));
- ToFlush();
- }
-
- protected int TimedFromReadChar() {
- if (opts.Timeout > 0)
- return FromReadChar((opts.Timeout + 1) * 1000);
- else
- return FromReadChar();
- }
-
- private void Trace(string msg) {
- Contract.Requires(msg != null);
- Console.WriteLine("Z3: " + msg);
- }
-
- public override ProverOutcome CheckOutcome(Microsoft.Boogie.ProverInterface.ErrorHandler handler) {
- //Contract.Requires(handler != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- //ProverOutcome outcome;
- bool isInvalid = false;
-
- if (this.simplify == null) {
- return ProverOutcome.Inconclusive;
- }
-
-
- while (true) {
- int ch = TimedFromReadChar();
- if (ch == -1 && this.readTimedOut) {
- handler.OnResourceExceeded("timeout (forced)");
- return ProverOutcome.TimeOut;
- }
-
- if (ch == -1)
- throw new UnexpectedProverOutputException("z3 crashed and produced no output");
-
- string line = new string((char)ch, 1) + FromReadLine();
-
- if (line.StartsWith("STATS ")) {
- if (inspector != null) {
- inspector.StatsLine(line);
- }
- continue;
- }
-
- if (opts.Verbosity > 2) {
- Trace("INPUT: " + line);
- }
-
- if (line.StartsWith("WARNING: Out of allocated virtual memory.")) {
- handler.OnResourceExceeded("memory");
- return ProverOutcome.OutOfMemory;
- }
-
-
- if (line.StartsWith("WARNING: ")) {
- string w = line.Substring(9);
- handler.OnProverWarning(w);
- continue;
- }
-
- if (line.ToUpper().StartsWith("ERROR")) {
- Console.WriteLine("Z3 returns the following error:");
- Console.WriteLine(" " + line);
- return ProverOutcome.Inconclusive;
- }
-
- int beg = 0;
- while (beg < line.Length && '0' <= line[beg] && line[beg] <= '9') {
- cce.LoopInvariant(beg <= line.Length);
- beg++;
- }
-
- if (beg > 0 && line.Substring(beg).StartsWith(": ")) {
- string status = line.Substring(beg + 2);
-
- if (status.StartsWith("Valid")) {
- return ProverOutcome.Valid;
- }
-
- if (status.StartsWith("Timeout")) {
- handler.OnResourceExceeded("timeout");
- return ProverOutcome.TimeOut;
- }
-
- if (status.StartsWith("Inconclusive")) {
- return ProverOutcome.Inconclusive;
- }
-
- if (status.StartsWith("Memout")) {
- handler.OnResourceExceeded("memory");
- return ProverOutcome.OutOfMemory;
- }
-
- if (status.StartsWith("Invalid")) {
- isInvalid = true;
- continue;
- }
- }
-
- if (isInvalid && line == ".") {
- return ProverOutcome.NotValid;
- }
-
- if (isInvalid && line.StartsWith("labels: (")) {
- List<string/*!*/>/*!*/ l = ParseLabels(line);
- Contract.Assert(cce.NonNullElements(l));
- Z3ErrorModel errModel = null;
- if (expectingModel) {
- if (opts.Verbosity > 2) {
- Trace("waiting for model");
- }
- line = FromReadLine();
- if (line.StartsWith("partitions:")) {
- line = ParseModel(out errModel);
- if (opts.Verbosity > 2) {
- Trace("model parsed, final line " + line);
- }
- // Z3 always ends the model with END_OF_MODEL, not with labels: or .
- Contract.Assume(line == "END_OF_MODEL");
- } else {
- throw new UnexpectedProverOutputException(string.Format("evil input from z3 (expecting partitions): '{0}'", line));
- }
- }
- handler.OnModel(l, errModel);
- continue;
- }
-
- throw new UnexpectedProverOutputException(string.Format("evil input from z3: '{0}'", line));
- }
- }
-
- /* ----------------------------------------------------------------------------
- BNF Grammar to parse Z3 output, including the model generated when using the /m /si switch:
-
- Output ::= VC*
- VC ::= number ": " "Valid." | number ": " "Inconclusive" | VCI
- VCI ::= number ": " "Invalid"
- ("labels: " "(" ID* ")"
- [MODEL] "END_OF_MODEL")+
- "."
- MODEL ::= MBOOL MFUNC
- MBOOL ::= "boolean assignment:"
- "partitions:"
- MAPPING*
- MAPPING ::= ZID ["{" ID+"}"] ["->" "(" (number | false | true | BITVECTOR) ")"]
- BITVECTOR ::= ulong ":bv" int
- MFUNC ::= "function interpretations:"
- F*
- F ::= Id "->" "{"
- MAPLET*
- "else" "->" ZID
- "}"
- MAPLET ::= ZID* "->" ZID
-
- -----------------------------------------------------------------------------*/
- private string ParseModel(out Z3ErrorModel errModel)
- //modifies this.*;
- //throws UnexpectedProverOutputException;
- {
- Contract.Ensures(Contract.Result<string>() == "." || Contract.Result<string>().StartsWith("labels: (") || Contract.Result<string>() == "END_OF_MODEL");
- Contract.Ensures(Contract.Result<string>() != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- //Format in the grammar:
- // ZID ["{" ID+"}"] ["->" "(" (number | false | true) ")"]
- // storing the model:
- // map each ID (a string) to the corresping ZID (an integer) in a dictionary:
- Dictionary<string/*!*/, int> identifierToPartition = new Dictionary<string/*!*/, int>();
- // map each ZID to the set (in list form) of IDs belonging to it (possibly empty):
- List<List<string/*!*/>> partitionToIdentifiers = new List<List<string/*!*/>>();
- // map each ZID to the number or boolean given, if any:
- List<Object> partitionToValue = new List<Object>();
- // map each value (number or boolean) to the ZID, reverse map of partitionToValue
- Dictionary<Object, int> valueToPartition = new Dictionary<Object, int>();
- cce.Owner.AssignSame(cce.Owner.ElementProxy(partitionToValue), cce.Owner.ElementProxy(valueToPartition));
-
- int ch;
-
- // read the MAPPING
- for (int zID = 0; true; zID++) {
- ch = FromReadChar();
- if (ch == 'f') {
- break;
- }
- ParseModelMapping(zID, identifierToPartition, partitionToIdentifiers, partitionToValue, valueToPartition);
- }// end MAPPING
-
- // add the fake partition for the 'else -> #undefined' clause
- List<string/*!*/> emptyList = new List<string/*!*/>();
- cce.Owner.AssignSame(emptyList, cce.Owner.ElementProxy(partitionToIdentifiers));
- partitionToIdentifiers.Add(emptyList);
- partitionToValue.Add(null);
-
- // continue in ParseModelFunctions, which breaks up this long method and enables its verification
- return ParseModelFunctions(ch, out errModel, identifierToPartition, partitionToIdentifiers, partitionToValue, valueToPartition);
- }
-
- private void ParseModelMapping(int zID,
- Dictionary<string/*!*/, int>/*!*/ identifierToPartition,
- List<List<string/*!*/>>/*!*/ partitionToIdentifiers,
- List<Object>/*!*/ partitionToValue,
- Dictionary<Object, int>/*!*/ valueToPartition)
- //modifies this.*, identifierToPartition.*, partitionToIdentifiers.*, partitionToValue.*, valueToPartition.*;
- {
- Contract.Requires(partitionToValue != null);
- Contract.Requires(valueToPartition != null);
- Contract.Requires(identifierToPartition != null);
- Contract.Requires(cce.NonNullElements(partitionToIdentifiers));
- Contract.Requires(cce.Owner.Same(cce.Owner.ElementProxy(partitionToValue), cce.Owner.ElementProxy(valueToPartition)));
- string s = FromReadLine();
- {
- // sanity check
- int pos = s.IndexOf(' ');
- string n = s;
- int k;
- if (pos >= 0) {
- n = s.Substring(0, pos);
- }
- if (!(int.TryParse(n, out k) && zID == k)) {
- System.Console.WriteLine("mismatch: {0}!={1} '{2}'", zID, k, s);
- Contract.Assume(false);
- }
- }
-
- int j = ParseModelZidAndIdentifiers(zID, s, identifierToPartition, partitionToIdentifiers);
-
- j = s.IndexOf(" -> ", j);
- if (0 <= j) {
- j += 4;
- }
- Contract.Assume(j == -1 || j < s.Length); // if ' -> ' is present, then more should remain of the line
- if (j == -1) {
- // no "-> " found, end of this line, store that there is no value:
- partitionToValue.Add(null);
- int idForNull;
- if (identifierToPartition.TryGetValue("nullObject", out idForNull) && idForNull == zID) {
- Contract.Assume(!valueToPartition.ContainsKey("nullObject")); // a RHS value should occur only once in the Z3 output
- valueToPartition.Add("nullObject", zID);
- // In this case partitionToValue (as the reverse of valueToPartition) should include
- // a map from zID -> "nullObject", but doing that breaks printing out the model as
- // it is printed out by Z3. Also, that information is not required, valueToPartition
- // works well enough by itself.
- }
-
- } else if (s[j] == 't'/*rue*/) {
- partitionToValue.Add(true);
- object boxedTrue = true;
- Contract.Assume(!valueToPartition.ContainsKey(boxedTrue)); // a RHS value should occur only once in the Z3 output
- valueToPartition.Add(boxedTrue, zID);
- } else if (s[j] == 'f'/*alse*/) {
- object boxedFalse = false;
- cce.Owner.AssignSame(boxedFalse, cce.Owner.ElementProxy(partitionToValue));
- partitionToValue.Add(boxedFalse);
- Contract.Assume(!valueToPartition.ContainsKey(boxedFalse)); // a RHS value should occur only once in the Z3 output
- valueToPartition.Add(boxedFalse, zID);
- } else if (s[j] == 'v') {
- // -> val!..., i.e. no value
- partitionToValue.Add(null);
- } else if (s[j] == '{') {
- // array
- List<List<int>/*!*/> arrayModel = new List<List<int>/*!*/>();
- Contract.Assert(Contract.ForAll(arrayModel, a => a != null));
- string array = s.Substring(j + 1);
- int index1, index2;
- string from, to;
- List<int> tuple = new List<int>();
- while (0 <= array.IndexOf(';')) {
- index1 = array.IndexOf('*') + 1;
- index2 = array.IndexOf(' ');
- from = array.Substring(index1, index2 - index1);
- tuple.Add(int.Parse(from));
- array = array.Substring(index2);
- index1 = array.IndexOf('*') + 1;
- index2 = array.IndexOf(';');
- to = array.Substring(index1, index2 - index1);
- array = array.Substring(index2 + 2);
- tuple.Add(int.Parse(to));
- arrayModel.Add(tuple);
- tuple = new List<int>();
- }
- Contract.Assert(array.StartsWith("else ->"));
- index1 = array.IndexOf('*') + 1;
- index2 = array.IndexOf('}');
- to = array.Substring(index1, index2 - index1);
- tuple.Add(int.Parse(to));
- arrayModel.Add(tuple);
- partitionToValue.Add(arrayModel);
- } else {
- string numberOrBv = s.Substring(j);
- // make number an int, then store it:
- BigNum bvVal;
- int bvSize;
- string number, type;
-
- int l = numberOrBv.IndexOf(':', 0);
- if (0 <= l) {
- number = numberOrBv.Substring(0, l);
- type = numberOrBv.Substring(l + 1);
- } else {
- l = numberOrBv.IndexOf('[', 0);
- if (0 <= l) {
- number = numberOrBv.Substring(2, l - 2);
- int closingBracePosition = numberOrBv.IndexOf(']', l);
- if (l < closingBracePosition)
- type = "bv" + numberOrBv.Substring(l + 1, closingBracePosition - l - 1);
- else type = "int";
- } else {
- number = numberOrBv;
- type = "int";
- }
- }
-
- if (type == "int") {
- object boxedN = BigNum.FromString(number);
- Contract.Assume(cce.Owner.None(boxedN));
- cce.Owner.AssignSame(boxedN, cce.Owner.ElementProxy(partitionToValue));
- partitionToValue.Add(boxedN);
- Contract.Assume(!valueToPartition.ContainsKey(boxedN)); // a RHS value should occur only once in the Z3 output
- valueToPartition.Add(boxedN, zID);
- } else if (type.StartsWith("bv") && BigNum.TryParse(number, out bvVal) && int.TryParse(type.Substring(2), out bvSize)) {
- BvConst bitV = new BvConst(bvVal, bvSize);
- cce.Owner.AssignSame(bitV, cce.Owner.ElementProxy(partitionToValue));
- partitionToValue.Add(bitV);
- Contract.Assume(!valueToPartition.ContainsKey(bitV)); // a RHS value should occur only once in the Z3 output
- valueToPartition.Add(bitV, zID);
- } else {
- System.Console.WriteLine("cannot parse type: '{0}':'{1}'", number, type);
- Contract.Assume(false);
- }
-
- }
- }
-
- private static int ParseModelZidAndIdentifiers(int zID, string s,
- Dictionary<string/*!*/, int>/*!*/ identifierToPartition,
- List<List<string/*!*/>>/*!*/ partitionToIdentifiers)
- //modifies identifierToPartition.*, partitionToIdentifiers.*;
- {
- Contract.Requires(identifierToPartition != null && cce.NonNullElements(identifierToPartition.Keys));
- Contract.Requires(partitionToIdentifiers != null && Contract.ForAll(partitionToIdentifiers, identifier => cce.NonNullElements(identifier)));
- Contract.Requires(s != null);
- Contract.Ensures(0 <= Contract.Result<int>() && Contract.Result<int>() <= s.Length);
-
- List<string/*!*/> identifiers = new List<string/*!*/>();
- int arrowIndex = s.IndexOf('>');
- Contract.Assert(0 < arrowIndex);
- int j = s.IndexOf('{', 0) + 1; // skip the '{', if present, and set j to 0 otherwise
- if (1 <= j && j < arrowIndex) {
- // There is a list of ID's.
- Contract.Assume(j < s.Length); // there should be more characters; the ending '}', for one
- //ID*
- while (true) {
- cce.LoopInvariant(cce.IsPeerConsistent(identifiers) && cce.IsPeerConsistent(identifierToPartition) && cce.IsPeerConsistent(partitionToIdentifiers));
- cce.LoopInvariant(0 <= j && j < s.Length);
- int k = s.IndexOfAny(new char[] { ' ', '}' }, j);
- Contract.Assume(j <= k);
- string id = s.Substring(j, k - j);
- j = k + 1;
- Contract.Assume(!identifierToPartition.ContainsKey(id)); // an ID is listed only once in this list, and an ID can only belong to one ZID equivalence class
- identifierToPartition.Add(id, zID);
- identifiers.Add(id);
- if (s[k] == '}') {
- // end of reading ID*
- break;
- }
- Contract.Assume(j < s.Length); // there should be more characters; the ending '}', for one
- }//end ID*
- } else {
- j = 0;
- }
- cce.Owner.AssignSame(identifiers, cce.Owner.ElementProxy(partitionToIdentifiers));
- partitionToIdentifiers.Add(identifiers);
- return j;
- }
-
- private string ParseModelFunctions(int ch, out Z3ErrorModel errModel,
- Dictionary<string/*!*/, int>/*!*/ identifierToPartition,
- List<List<string/*!*/>>/*!*/ partitionToIdentifiers,
- List<Object>/*!*/ partitionToValue,
- Dictionary<Object, int>/*!*/ valueToPartition
- )
- //modifies this.*;
- {
- Contract.Requires(identifierToPartition != null && cce.NonNullElements(identifierToPartition.Keys));
- Contract.Requires(partitionToIdentifiers != null && Contract.ForAll(partitionToIdentifiers, identifier => cce.NonNullElements(identifier)));
- Contract.Requires(partitionToValue != null);
- Contract.Requires(valueToPartition != null);
- Contract.Ensures(Contract.Result<string>() != null);
- Contract.Ensures(Contract.Result<string>() == "." || Contract.Result<string>().StartsWith("labels: (") || Contract.Result<string>() == "END_OF_MODEL");
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- // read the function F
- Expect(ch, "function interpretations:");
- FromReadLine();
-
- // mapping of function names to function definitions
- Dictionary<string/*!*/, List<List<int>>/*!*/> definedFunctions = new Dictionary<string/*!*/, List<List<int>>/*!*/>();
- // function definition given as list of 'pointwise definitions' in the form of the arguments and result
- // the last element here will always be a list with just one entry which corresponds to the else case
- List<List<int>> functionDefinition = new List<List<int>>();
- // list of arguments, followed by the result, the last element of this list is always the result
- List<int> argumentsAndResult = new List<int>();
-
- // read F
- while (true) {
- functionDefinition = new List<List<int>>();
- string s = FromReadLine();
- // end of F, "END_OF_MODEL" ends model, '.' ends whole VC, 'l' starts a new set of labels and model
- // whenever there is a model this will end with "END_OF_MODEL", the other cases can only
- // happen when there is no model printed!
- if (s == "." || s.StartsWith("labels: (") || s == "END_OF_MODEL") {
- errModel = new Z3ErrorModel(identifierToPartition, partitionToIdentifiers, partitionToValue, valueToPartition, definedFunctions);
- return s;
- }
- int j = s.IndexOf(' ', 0);
- Contract.Assume(0 <= j);
- string id = s.Substring(0, j);
- // id is stored into definedFunctions once the function definition for it has
- // been completely parsed.
-
- if (s.IndexOf("-> {") < 0) {
- // This function was a macro and we are not parsing its definition currently.
- // Just move on to the next function.
- while (true) {
- s = FromReadLine();
- if (0 <= s.IndexOf("{" + id + "}"))
- break;
- }
- continue;
- }
-
- // just ignore the "-> {" by dropping string s
- string zIDstring;
-
- // MAPLET
- while (true) {
- argumentsAndResult = new List<int>();
- // remove the 2 spaces that are here
- FromReadChar();
- FromReadChar();
- s = FromReadLine();
- if (s.StartsWith("else ->")) break;
- j = 0;
-
- //ZID*
- while (true) {
- cce.LoopInvariant(0 <= j && j <= s.Length);
-
- j = s.IndexOfAny(new Char[] { '*', '-' }, j);
- // true because this always ends with a "->":
- Contract.Assume(0 <= j);
-
- // reading -> means end of ZID*
- if (s[j] == '-'/*>*/) break;
-
- // start reading the ZID* with the number, not the *
- j = j + 1;
- // by input string format:
- Contract.Assume(j < s.Length);
- int k = s.IndexOf(' ', j);
- // by input string format:
- Contract.Assume(j <= k);
- zIDstring = s.Substring(j, k - j);
- // add the arguments
- argumentsAndResult.Add(int.Parse(zIDstring));
- j = k;
- }// end ZID*
-
- // j is the beginning of "-> *", we want the first character after this
- j = j + 4;
- // by input string format:
- Contract.Assume(j <= s.Length);
- zIDstring = s.Substring(j);
- // add the result
- argumentsAndResult.Add(int.Parse(zIDstring));
- // add the input line as another 'pointwise defined' element to the functions definition
- functionDefinition.Add(argumentsAndResult);
- }// end MAPLET
-
- // this is the 'else -> #unspecified' case
- // by input string format:
- Contract.Assume(s.IndexOf("#unspec") >= 0);
- // this stores the else line as another argumentsAndResult list
- argumentsAndResult = new List<int>();
- argumentsAndResult.Add(partitionToIdentifiers.Count - 1); // use the fake partition we have created before
- // which is then added to the function definition, which is now complete
- cce.Owner.AssignSame(argumentsAndResult, cce.Owner.ElementProxy(functionDefinition));
- functionDefinition.Add(argumentsAndResult);
-
- /*
- // this is the 'else -> *' case, that string is already in s
- j = s.IndexOf('*', 0) + 1;
- // by input string format:
- assume 0 < j && j < s.Length;
- zIDstring = s.Substring(j);
- // this stores the else line as another argumentsAndResult list
- argumentsAndResult = new List<int>();
- argumentsAndResult.Add(int.Parse(zIDstring));
- // which is then added to the function definition, which is now complete
- functionDefinition.Add(argumentsAndResult); */
-
- // and therefore added to the map of defined functions, together with the name 'id'
- // which had been extracted before
- Contract.Assume(!definedFunctions.ContainsKey(id)); // each function name in the model is listed only once
- definedFunctions.Add(id, functionDefinition);
-
- // read the line with "}"
- ch = FromReadChar();
- Expect(ch, "}");
- FromReadLine();
- }// end F
- }
-
- }
-
-
- public class Z3ErrorModel : ErrorModel
- {
- public Z3ErrorModel(Dictionary<string/*!*/, int>/*!*/ identifierToPartition,
- List<List<string/*!*/>>/*!*/ partitionToIdentifiers,
- List<Object>/*!*/ partitionToValue,
- Dictionary<object, int>/*!*/ valueToPartition,
- Dictionary<string/*!*/, List<List<int>>/*!*/>/*!*/ definedFunctions)
- : base(identifierToPartition, partitionToIdentifiers, partitionToValue, valueToPartition, definedFunctions) {
- Contract.Requires(identifierToPartition != null && cce.NonNullElements(identifierToPartition.Keys));
- Contract.Requires(partitionToIdentifiers != null && Contract.ForAll(partitionToIdentifiers, x => cce.NonNullElements(x)));
- Contract.Requires(partitionToValue != null);
- Contract.Requires(valueToPartition != null);
- Contract.Requires(definedFunctions != null && cce.NonNullElements(definedFunctions.Keys) && cce.NonNullElements(definedFunctions.Values));
-
- this.partitionNames = new string/*?*/[partitionToIdentifiers.Count];
- this.prevPartitionNames = new string/*?*/[partitionToIdentifiers.Count];
- }
-
- private string/*?*/[]/*!*/ partitionNames;
- private string/*?*/[]/*!*/ prevPartitionNames;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(partitionNames != null);
- Contract.Invariant(prevPartitionNames != null);
- }
-
-
- private void SetNames() {
- int len = partitionToIdentifiers.Count;
- for (int i = 0; i < 3; ++i) { // let the names stabilize a bit
- prevPartitionNames = partitionNames;
- partitionNames = new string[len];
- for (int pos = 0; pos < len; ++pos)
- GetPartitionName(pos);
- }
- }
-
- private int NameBadness(string name) {
- Contract.Requires(name != null);
- int badness = name.Length;
- if (name.StartsWith("call") && name.IndexOf("formal@") > 0)
- badness += 1000;
- if (name.IndexOf("(") > 0)
- badness += 500;
- return badness;
- }
-
- private string GetPartitionName(int pos) {
- Contract.Ensures(Contract.Result<string>() != null);
-
- string name = partitionNames[pos];
- if (name != null) {
- return name;
- }
-
- object tmp = partitionToValue[pos];
- if (tmp != null) {
- partitionNames[pos] = tmp is BvConst ? ((BvConst)tmp).ToReadableString() : tmp.ToString();
- } else {
- List<string/*!*/>/*!*/ possible_names = new List<string/*!*/>();
- List<string/*!*/> pti = partitionToIdentifiers[pos];
- Contract.Assert(cce.NonNullElements(pti));
-
- // make sure we're not called recursively
- string prevName = prevPartitionNames[pos];
- if (prevName == null) prevName = "*" + pos;
- partitionNames[pos] = prevName;
-
- if (pti != null && pti.Count > 0) {
- // add identifiers
- foreach (string n in pti) {
- Contract.Assert(n != null);
- possible_names.Add(n);
- }
- }
-
- // Then also look for functions,
- // and then collect possible functional definitions
- foreach (KeyValuePair<string/*!*/, List<List<int>>/*!*/> kv in definedFunctions) {
- Contract.Assert(kv.Key != null);
- Contract.Assert(kv.Value != null);
- foreach (List<int> parms in kv.Value) {
- if (parms.Count > 1 && parms[parms.Count - 1] == pos) {
- string s = kv.Key + "(";
- for (int i = 0; i < parms.Count - 1; ++i) {
- if (i != 0) s += ", ";
- s += GetPartitionName(parms[i]);
- }
- s += ")";
- possible_names.Add(s);
- }
- }
- }
-
- // choose the shortest possible name
- if (possible_names.Count > 0) {
- string best = possible_names[0];
- foreach (string s in possible_names) {
- Contract.Assert(s != null);
- if (NameBadness(s) < NameBadness(best)) best = s;
- }
- if (best.Length < 120)
- partitionNames[pos] = best;
- }
- }
-
- return cce.NonNull(partitionNames[pos]);
- }
-
- private void PrintReadableModel(TextWriter writer) {
- Contract.Requires(writer != null);
- writer.WriteLine("Z3 error model: ");
- SetNames();
- writer.WriteLine("partitions:");
- Contract.Assert(partitionToIdentifiers.Count == partitionToValue.Count);
- for (int i = 0; i < partitionToIdentifiers.Count; i++) {
- writer.Write("{0,5}: {1} ", "*" + i, GetPartitionName(i));
- List<string/*!*/> pti = partitionToIdentifiers[i];
- Contract.Assert(cce.NonNullElements(pti));
- if (pti != null && (pti.Count > 1 || (pti.Count == 1 && partitionToValue[i] != null))) {
- writer.Write("{");
- for (int k = 0; k < pti.Count - 1; k++) {
- writer.Write(pti[k] + " ");
- }
- //extra work to make sure no " " is at the end of the list of identifiers
- if (pti.Count != 0) {
- writer.Write(pti[pti.Count - 1]);
- }
- writer.Write("}");
- }
- writer.WriteLine();
- }
-
- writer.WriteLine();
- writer.WriteLine("function interpretations:");
- List<string> funNames = new List<string>(definedFunctions.Keys);
- funNames.Sort();
- foreach (string name in funNames) {
- Contract.Assert(name != null);
- if (definedFunctions[name].Count == 1) continue; // skip functions with only the else-> clause
- foreach (List<int> parms in definedFunctions[name]) {
- Contract.Assert(parms != null);
- string s = name + "(";
- if (parms.Count == 1) {
- continue;
- // s += "*";
- } else {
- for (int i = 0; i < parms.Count - 1; ++i) {
- if (i != 0) s += ", ";
- s += GetPartitionName(parms[i]);
- }
- }
- s += ")";
- string res = GetPartitionName(parms[parms.Count - 1]);
- if (res == s)
- res = "*" + parms[parms.Count - 1] + " (SELF)";
- writer.WriteLine("{0} = {1}", s, res);
- }
- writer.WriteLine();
- }
- writer.WriteLine("The end.");
- writer.WriteLine();
- }
-
- public override void Print(TextWriter writer) {
- //Contract.Requires(writer != null);
- if (CommandLineOptions.Clo.PrintErrorModel == 4) {
- PrintReadableModel(writer);
- } else {
- base.Print(writer);
- }
- }
- }
-}
-
-
diff --git a/Source/Provers/Z3/ProverInterface.cs b/Source/Provers/Z3/ProverInterface.cs
deleted file mode 100644
index 3718372b..00000000
--- a/Source/Provers/Z3/ProverInterface.cs
+++ /dev/null
@@ -1,427 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-//using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-//using System.IO;
-using System.Text;
-//using ExternalProver;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.AbstractInterpretation;
-using Microsoft.Boogie;
-using Microsoft.Boogie.VCExprAST;
-using Microsoft.Boogie.Clustering;
-using Microsoft.Boogie.TypeErasure;
-using Microsoft.Boogie.Z3;
-using Microsoft.Boogie.Simplify;
-
-namespace Microsoft.Boogie.Z3
-{
- public class Z3ProcessTheoremProver : ProcessTheoremProver
- {
- private Z3InstanceOptions opts;
- private Inspector inspector;
- [ContractInvariantMethod]
-void ObjectInvariant()
-{
- Contract.Invariant(opts!=null);
-}
-
-
- [NotDelayed]
- public Z3ProcessTheoremProver(VCExpressionGenerator gen,
- DeclFreeProverContext ctx, Z3InstanceOptions opts):base(opts, gen, ctx, opts.ExeName, "TypedUnivBackPred2.sx")
- {
- Contract.Requires(gen != null);
- Contract.Requires(ctx != null);
- Contract.Requires(opts != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- this.opts = opts;
-
- }
-
- private void FireUpInspector()
- {
- if (inspector == null && opts.Inspector != null) {
- inspector = new Inspector(opts);
- }
- }
-
- protected override Microsoft.Boogie.Simplify.ProverProcess CreateProverProcess(string proverPath) {
- //Contract.Requires(proverPath!= null);
- Contract.Ensures(Contract.Result<Microsoft.Boogie.Simplify.ProverProcess>() != null);
-
-
- opts.ExeName = proverPath;
- FireUpInspector();
- if (inspector != null) {
- inspector.NewProver();
- }
- return new Z3ProverProcess(opts, inspector);
- }
-
- protected override AxiomVCExprTranslator SpawnVCExprTranslator(ProverOptions opts) {
- //Contract.Requires(opts != null);
- Contract.Ensures(Contract.Result<AxiomVCExprTranslator>() != null);
-
- return new Z3VCExprTranslator(gen, (Z3InstanceOptions) opts);
- }
-
- public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler)
- {
- //Contract.Requires(descriptiveName != null);
- //Contract.Requires(vc != null);
- //Contract.Requires(handler != null);
- FireUpInspector();
- if (inspector != null) {
- inspector.NewProblem(descriptiveName, vc, handler);
- }
- base.BeginCheck(descriptiveName, vc, handler);
- }
- }
-
- public class Z3InstanceOptions : ProverOptions
- {
- public int Timeout { get { return TimeLimit / 1000; } }
- public int Lets {
- get
- {
- Contract.Ensures(0 <= Contract.Result<int>() && Contract.Result<int>() < 4);
- return CommandLineOptions.Clo.Z3lets;
- }
- }
- public bool DistZ3 = false;
- public string ExeName = "z3.exe";
- public bool InverseImplies = false;
- public string Inspector = null;
- public bool OptimizeForBv = false;
-
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(ExeName!=null);
- }
-
- protected override bool Parse(string opt)
- {
- //Contract.Requires(opt!=null);
- return ParseBool(opt, "REVERSE_IMPLIES", ref InverseImplies) ||
- ParseString(opt, "INSPECTOR", ref Inspector) ||
- ParseBool(opt, "DIST", ref DistZ3) ||
- ParseBool(opt, "OPTIMIZE_FOR_BV", ref OptimizeForBv) ||
- base.Parse(opt);
- }
-
- public override void PostParse()
- {
- base.PostParse();
-
- if (DistZ3) {
- ExeName = "z3-dist.exe";
- CommandLineOptions.Clo.RestartProverPerVC = true;
- }
- }
-
- public override string Help
- {
- get
- {
- return
-@"
-Z3-specific options:
-~~~~~~~~~~~~~~~~~~~~
-INSPECTOR=<string> Use the specified Z3Inspector binary.
-OPTIMIZE_FOR_BV=<bool> Optimize Z3 options for bitvector reasoning, and not quantifier instantiation. Defaults to false.
-
-Obscure options:
-~~~~~~~~~~~~~~~~
-DIST=<bool> Use z3-dist.exe binary.
-REVERSE_IMPLIES=<bool> Encode P==>Q as Q||!P.
-
-" + base.Help;
- // DIST requires non-public binaries
- }
- }
- }
-
- public class Z3LineariserOptions : LineariserOptions {
- private readonly Z3InstanceOptions opts;
-
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(opts!=null);
- }
-
-
- public Z3LineariserOptions(bool asTerm, Z3InstanceOptions opts, List<VCExprVar/*!>!*/> letVariables):base(asTerm) {
- Contract.Requires(opts != null);
- Contract.Requires(cce.NonNullElements(letVariables));
-
- this.opts = opts;
- this.LetVariablesAttr = letVariables;
- }
-
- public override bool UseWeights { get {
- return true;
- } }
-
- public override bool UseTypes { get {
- return true;
- } }
-
- public override bool QuantifierIds { get {
- return true;
- } }
-
- public override bool InverseImplies { get {
- return opts.InverseImplies;
- } }
-
- public override LineariserOptions SetAsTerm(bool newVal) {
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
-
- if (newVal == AsTerm)
- return this;
- return new Z3LineariserOptions(newVal, opts, LetVariables);
- }
-
- // variables representing formulas in let-bindings have to be
- // printed in a different way than other variables
- private readonly List<VCExprVar/*!>!*/> LetVariablesAttr;
- public override List<VCExprVar/*!>!*/> LetVariables { get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
-
- return LetVariablesAttr;
- } }
-
- public override LineariserOptions AddLetVariable(VCExprVar furtherVar) {
- //Contract.Requires(furtherVar != null);
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
-
- List<VCExprVar/*!>!*/> allVars = new List<VCExprVar/*!*/>();
- allVars.AddRange(LetVariables);
- allVars.Add(furtherVar);
- return new Z3LineariserOptions(AsTerm, opts, allVars);
- }
-
- public override LineariserOptions AddLetVariables(List<VCExprVar/*!>!*/> furtherVars) {
- //Contract.Requires(furtherVars != null);
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
-
- List<VCExprVar/*!>!*/> allVars = new List<VCExprVar/*!*/> ();
- allVars.AddRange(LetVariables);
- allVars.AddRange(furtherVars);
- return new Z3LineariserOptions(AsTerm, opts, allVars);
- }
- }
-
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
-
- public class Z3VCExprTranslator : AxiomVCExprTranslator {
- public Z3VCExprTranslator(VCExpressionGenerator gen, Z3InstanceOptions opts) {
- Contract.Requires(gen != null);
- Contract.Requires(opts != null);
- Gen = gen;
- Opts = opts;
- TypeAxiomBuilder axBuilder;
- switch (CommandLineOptions.Clo.TypeEncodingMethod) {
- case CommandLineOptions.TypeEncoding.Arguments:
- axBuilder = new TypeAxiomBuilderArguments (gen);
- break;
- default:
- axBuilder = new TypeAxiomBuilderPremisses (gen);
- break;
- }
- axBuilder.Setup();
- AxBuilder = axBuilder;
- UniqueNamer namer = new UniqueNamer ();
- Namer = namer;
- this.DeclCollector =
- new TypeDeclCollector (namer, true);
- }
-
- private Z3VCExprTranslator(Z3VCExprTranslator tl) :base(tl){
- Contract.Requires(tl!=null);
- Gen = tl.Gen;
- Opts = tl.Opts; // we assume that the options have not changed
- AxBuilder = (TypeAxiomBuilder)tl.AxBuilder.Clone();
- UniqueNamer namer = (UniqueNamer)tl.Namer.Clone();
- Namer = namer;
- DeclCollector = new TypeDeclCollector (namer, tl.DeclCollector);
- }
-
- public override Object Clone() {
- Contract.Ensures(Contract.Result<Object>() != null);
-
- return new Z3VCExprTranslator(this);
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(Opts!=null);
- Contract.Invariant(Gen != null);
- Contract.Invariant(AxBuilder != null);
- Contract.Invariant(Namer != null);
- Contract.Invariant(DeclCollector != null);
- }
-
- private readonly Z3InstanceOptions Opts;
- private readonly VCExpressionGenerator Gen;
- private readonly TypeAxiomBuilder AxBuilder;
- private readonly UniqueNamer Namer;
- private readonly TypeDeclCollector DeclCollector;
-
- public override string Lookup(VCExprVar var)
- {
- //Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- VCExprVar v = AxBuilder.TryTyped2Untyped(var);
- if (v != null) {
- var = v;
- }
- return Namer.Lookup(var);
- }
-
- public override string translate(VCExpr expr, int polarity) {
- //Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- DateTime start = DateTime.UtcNow;
- if (CommandLineOptions.Clo.Trace)
- Console.Write("Linearising ... ");
-
- // handle the types in the VCExpr
- TypeEraser eraser;
- switch (CommandLineOptions.Clo.TypeEncodingMethod) {
- case CommandLineOptions.TypeEncoding.Arguments:
- eraser = new TypeEraserArguments((TypeAxiomBuilderArguments)AxBuilder, Gen);
- break;
- case CommandLineOptions.TypeEncoding.Monomorphic:
- eraser = null;
- break;
- default:
- eraser = new TypeEraserPremisses((TypeAxiomBuilderPremisses)AxBuilder, Gen);
- break;
- }
- VCExpr exprWithoutTypes = eraser != null ? eraser.Erase(expr, polarity) : expr;
- Contract.Assert(exprWithoutTypes!=null);
-
- LetBindingSorter letSorter = new LetBindingSorter(Gen);
- Contract.Assert(letSorter!=null);
- VCExpr sortedExpr = letSorter.Mutate(exprWithoutTypes, true);
- Contract.Assert(sortedExpr!=null);
- VCExpr sortedAxioms = letSorter.Mutate(AxBuilder.GetNewAxioms(), true);
- Contract.Assert(sortedAxioms!=null);
-
- DeclCollector.Collect(sortedAxioms);
- DeclCollector.Collect(sortedExpr);
- FeedTypeDeclsToProver();
- if (Opts.Lets != 3) {
- // replace let expressions with implies
- Let2ImpliesMutator letImplier = new Let2ImpliesMutator(Gen, Opts.Lets == 1, Opts.Lets == 2);
- sortedExpr = letImplier.Mutate(sortedExpr);
- sortedAxioms = letImplier.Mutate(sortedAxioms);
- }
-
- //////////////////////////////////////////////////////////////////////////
- //SubtermCollector! coll = new SubtermCollector (gen);
- //coll.Traverse(sortedExpr, true);
- //coll.Traverse(sortedAxioms, true);
- //coll.UnifyClusters();
- //Console.WriteLine(coll);
- //////////////////////////////////////////////////////////////////////////
-
- LineariserOptions linOptions = new Z3LineariserOptions(false, Opts, new List<VCExprVar/*!*/>());
-
- AddAxiom(SimplifyLikeExprLineariser.ToString(sortedAxioms, linOptions, Namer));
-
- string res = SimplifyLikeExprLineariser.ToString(sortedExpr, linOptions, Namer);
- Contract.Assert(res!=null);
-
- if (CommandLineOptions.Clo.Trace) {
- TimeSpan elapsed = DateTime.UtcNow - start;
- Console.WriteLine("finished [{0} s]", elapsed.TotalSeconds);
- }
- return res;
- }
-
- private void FeedTypeDeclsToProver() {
- foreach (string s in DeclCollector.GetNewDeclarations()) {
- Contract.Assert(s != null);
- AddTypeDecl(s);
- }
- }
- }
-
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
-
- public class Factory : ProverFactory
- {
-
- public override object SpawnProver(ProverOptions popts, object ctxt)
- {
- //Contract.Requires(popts != null);
- //Contract.Requires(ctxt != null);
- Contract.Ensures(Contract.Result<object>() != null);
-
- Z3InstanceOptions opts = cce.NonNull((Z3InstanceOptions)popts);
- return this.SpawnProver(cce.NonNull((DeclFreeProverContext)ctxt).ExprGen,
- cce.NonNull((DeclFreeProverContext)ctxt),
- opts);
- }
-
- public override object NewProverContext(ProverOptions options) {
- //Contract.Requires(options != null);
- //Contract.Ensures(Contract.Result<object>() != null);
-
- if (CommandLineOptions.Clo.BracketIdsInVC < 0) {
- CommandLineOptions.Clo.BracketIdsInVC = 0;
- }
-
- Z3InstanceOptions opts = cce.NonNull((Z3InstanceOptions)options);
- VCExpressionGenerator gen = new VCExpressionGenerator ();
- List<string/*!>!*/> proverCommands = new List<string/*!*/> ();
- proverCommands.Add("z3");
- proverCommands.Add("simplifyLike");
- VCGenerationOptions genOptions = new VCGenerationOptions(proverCommands);
-
- return NewProverContext(gen, genOptions, opts);
- }
-
- public override ProverOptions BlankProverOptions()
- {
- Contract.Ensures(Contract.Result<ProverOptions>() != null);
- return new Z3InstanceOptions();
- }
-
- protected virtual Z3ProcessTheoremProver SpawnProver(VCExpressionGenerator gen,
- DeclFreeProverContext ctx,
- Z3InstanceOptions opts) {
- Contract.Requires(gen != null);
- Contract.Requires(ctx != null);
- Contract.Requires(opts != null);
- Contract.Ensures(Contract.Result<Z3ProcessTheoremProver>() != null);
-
- return new Z3ProcessTheoremProver(gen, ctx, opts);
- }
-
- protected virtual DeclFreeProverContext NewProverContext(VCExpressionGenerator gen,
- VCGenerationOptions genOptions,
- Z3InstanceOptions opts)
- {
- return new DeclFreeProverContext(gen, genOptions);
- }
- }
-}
diff --git a/Source/Provers/Z3/TypeDeclCollector.cs b/Source/Provers/Z3/TypeDeclCollector.cs
deleted file mode 100644
index 19c88409..00000000
--- a/Source/Provers/Z3/TypeDeclCollector.cs
+++ /dev/null
@@ -1,398 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.Z3
-{
- // Visitor for collecting the occurring function symbols in a VCExpr,
- // and for creating the corresponding declarations that can be fed into
- // Z3
-
- // (should this be rather done by Context.DeclareFunction? right now,
- // the TypeErasure visitor introduces new function symbols that are
- // not passed to this method)
-
- public class TypeDeclCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
-
- private readonly UniqueNamer Namer;
- [ContractInvariantMethod]
-void ObjectInvariant()
-{
- Contract.Invariant(Namer!=null);
- Contract.Invariant(AllDecls != null);
- Contract.Invariant(IncDecls != null);
- Contract.Invariant(cce.NonNull(KnownFunctions));
- Contract.Invariant(cce.NonNull(KnownVariables));
- Contract.Invariant(cce.NonNull(KnownTypes));
- Contract.Invariant(cce.NonNull(KnownBvOps));
- Contract.Invariant(cce.NonNull(KnownSelectFunctions));
- Contract.Invariant(cce.NonNull(KnownStoreFunctions));
-}
-
-
- private readonly bool NativeBv;
-
- public TypeDeclCollector(UniqueNamer namer, bool nativeBv) {
- Contract.Requires(namer != null);
- this.Namer = namer;
- this.NativeBv = nativeBv;
- AllDecls = new List<string/*!*/> ();
- IncDecls = new List<string/*!*/> ();
- KnownFunctions = new HashSet<Function/*!*/>();
- KnownVariables = new HashSet<VCExprVar/*!*/>();
- KnownTypes = new HashSet<Type/*!*/>();
- KnownBvOps = new HashSet<string/*!*/>();
-
- KnownStoreFunctions = new HashSet<string/*!*/>();
- KnownSelectFunctions = new HashSet<string/*!*/>();
- }
-
- internal TypeDeclCollector(UniqueNamer namer, TypeDeclCollector coll) {
- Contract.Requires(namer!=null);
- Contract.Requires(coll!=null);
- this.Namer = namer;
- this.NativeBv = coll.NativeBv;
- AllDecls = new List<string/*!*/> (coll.AllDecls);
- IncDecls = new List<string/*!*/> (coll.IncDecls);
- KnownFunctions = new HashSet<Function/*!*/>(coll.KnownFunctions);
- KnownVariables = new HashSet<VCExprVar/*!*/>(coll.KnownVariables);
- KnownTypes = new HashSet<Type/*!*/>(coll.KnownTypes);
- KnownBvOps = new HashSet<string/*!*/>(coll.KnownBvOps);
-
- KnownStoreFunctions = new HashSet<string/*!*/>(coll.KnownStoreFunctions);
- KnownSelectFunctions = new HashSet<string/*!*/>(coll.KnownSelectFunctions);
- }
-
- // not used
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node != null);
- return true;
- }
-
- private readonly List<string/*!>!*/> AllDecls;
- private readonly List<string/*!>!*/> IncDecls;
-
- private readonly HashSet<Function/*!*/>/*!*/ KnownFunctions;
- private readonly HashSet<VCExprVar/*!*/>/*!*/ KnownVariables;
-
- // bitvector types have to be registered as well
- private readonly HashSet<Type/*!*/>/*!*/ KnownTypes;
-
- // the names of registered BvConcatOps and BvExtractOps
- private readonly HashSet<string/*!*/>/*!*/ KnownBvOps;
-
- private readonly HashSet<string/*!*/>/*!*/ KnownStoreFunctions;
- private readonly HashSet<string/*!*/>/*!*/ KnownSelectFunctions;
-
- public List<string/*!>!*/> AllDeclarations { get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>()));
-
- List<string/*!>!*/> res = new List<string/*!*/> ();
- res.AddRange(AllDecls);
- return res;
- } }
-
- public List<string/*!>!*/> GetNewDeclarations() {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>()));
- List<string/*!>!*/> res = new List<string/*!*/> ();
- res.AddRange(IncDecls);
- IncDecls.Clear();
- return res;
- }
-
- private void AddDeclaration(string decl) {
- Contract.Requires(decl != null);
- AllDecls.Add(decl);
- IncDecls.Add(decl);
- }
-
- public void Collect(VCExpr expr) {
- Contract.Requires(expr != null);
- Traverse(expr, true);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- private static string TypeToString(Type t) {
- Contract.Requires(t!= null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- return SimplifyLikeExprLineariser.TypeToString(t);
- }
-
- private void RegisterType(Type type)
- {
- Contract.Requires(type != null);
- if (KnownTypes.Contains(type)) return;
-
- if (type.IsMap && CommandLineOptions.Clo.MonomorphicArrays) {
- KnownTypes.Add(type);
- string declString = "";
- MapType mapType = type.AsMap;
- Contract.Assert(mapType != null);
-
- foreach (Type t in mapType.Arguments) {
- Contract.Assert(t != null);
- RegisterType(t);
- }
- RegisterType(mapType.Result);
-
- declString += "(DEFTYPE " + TypeToString(type);
-
- if (CommandLineOptions.Clo.UseArrayTheory) {
- declString += " :BUILTIN Array ";
- foreach (Type t in mapType.Arguments) {
- declString += TypeToString(t);
- declString += " ";
- }
- declString += TypeToString(mapType.Result);
- }
-
- declString += ")";
- AddDeclaration(declString);
- return;
- }
-
- if (type.IsBv && NativeBv) {
- int bits = type.BvBits;
- string name = TypeToString(type);
-
- AddDeclaration("(DEFTYPE " + name + " :BUILTIN BitVec " + bits + ")");
- // If we add the BUILTIN then the conversion axiom does not work
- AddDeclaration("(DEFOP " + name + "_to_int " + name + " $int)"); // :BUILTIN bv2int $int)");
- AddDeclaration("(DEFOP $make_bv" + bits + " $int " + name + " :BUILTIN int2bv " + bits + ")");
- string expr = "($make_bv" + bits + " (" + name + "_to_int x))";
- AddDeclaration("(BG_PUSH (FORALL (x :TYPE " + name + ") (PATS "
- + expr + ") (QID bvconv" + bits + ") (EQ " + expr + " x)))");
-
- KnownTypes.Add(type);
- return;
- }
-
- if (type.IsBool || type.IsInt)
- return;
-
- if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.Monomorphic) {
- AddDeclaration("(DEFTYPE " + TypeToString(type) + ")");
- KnownTypes.Add(type);
- return;
- }
-
- }
-
- public override bool Visit(VCExprNAry node, bool arg) {
- Contract.Requires(node != null);
- // there are a couple cases where operators have to be
- // registered by generating appropriate Z3 statements
-
- if (node.Op is VCExprBvOp) {
- if (NativeBv) {
- RegisterType(node[0].Type);
- RegisterType(node.Type);
- }
- } else if (node.Op is VCExprBvConcatOp) {
- //
- if (NativeBv) {
- RegisterType(node[0].Type);
- RegisterType(node[1].Type);
- RegisterType(node.Type);
-
- string name = SimplifyLikeExprLineariser.BvConcatOpName(node);
- if (!KnownBvOps.Contains(name)) {
- AddDeclaration("(DEFOP " + name +
- " " + TypeToString(node[0].Type) +
- " " + TypeToString(node[1].Type) +
- " " + TypeToString(node.Type) +
- " :BUILTIN concat)");
- KnownBvOps.Add(name);
- }
- }
- //
- } else if (node.Op is VCExprBvExtractOp) {
- //
- if (NativeBv) {
- RegisterType(node[0].Type);
- RegisterType(node.Type);
-
- VCExprBvExtractOp op = (VCExprBvExtractOp)node.Op;
- Contract.Assert(op!=null);
- string name = SimplifyLikeExprLineariser.BvExtractOpName(node);
- if (!KnownBvOps.Contains(name)) {
- AddDeclaration("(DEFOP " + name +
- " " + TypeToString(node[0].Type) +
- " " + TypeToString(node.Type) +
- " :BUILTIN extract " +
- (op.End - 1) + " " + op.Start + ")");
- KnownBvOps.Add(name);
- }
- }
- //
- } else if (node.Op is VCExprStoreOp) {
- RegisterType(node.Type); // this is the map type, registering it should register also the index and value types
- string name = SimplifyLikeExprLineariser.StoreOpName(node);
- if (!KnownStoreFunctions.Contains(name)) {
- string decl = "(DEFOP " + name;
-
- foreach (VCExpr ch in node) {
- decl += " " + TypeToString(ch.Type);
- }
- decl += " " + TypeToString(node.Type);
-
- if (CommandLineOptions.Clo.UseArrayTheory)
- decl += " :BUILTIN store";
- decl += ")";
- AddDeclaration(decl);
-
- if (CommandLineOptions.Clo.MonomorphicArrays && !CommandLineOptions.Clo.UseArrayTheory) {
- var sel = SimplifyLikeExprLineariser.SelectOpName(node);
-
- if (!KnownSelectFunctions.Contains(name)) {
- // need to declare it before reference
- string seldecl = "(DEFOP " + sel;
- foreach (VCExpr ch in node) {
- seldecl += " " + TypeToString(ch.Type);
- }
- AddDeclaration(seldecl + ")");
- KnownSelectFunctions.Add(name);
- }
-
- var eq = "EQ";
- if (node[node.Arity - 1].Type.IsBool)
- eq = "IFF";
-
- string ax1 = "(BG_PUSH (FORALL (";
- string ax2 = "(BG_PUSH (FORALL (";
- string argX = "", argY = "";
- string dist = "";
- for (int i = 0; i < node.Arity; i++) {
- var t = " :TYPE " + TypeToString(node[i].Type);
- var x = " x" + i;
- var y = " y" + i;
- ax1 += x + t;
- ax2 += x + t;
- if (i != 0 && i != node.Arity - 1) {
- argX += x;
- argY += y;
- ax2 += y + t;
- dist += " (NEQ" + x + y + ")";
- }
- }
- string v = " x" + (node.Arity - 1);
- ax1 += ") ";
- ax1 += "(" + eq + " (" + sel + " (" + name + " x0" + argX + v + ")" + argX + ") " + v + ")";
- ax1 += "))";
-
- ax2 += ") ";
- ax2 += "(IMPLIES (OR " + dist + ") (" + eq + " (" + sel + " (" + name + " x0" + argX + v + ")" + argY + ") (" + sel + " x0" + argY + ")))";
- ax2 += "))";
-
- AddDeclaration(ax1);
- AddDeclaration(ax2);
- }
-
- KnownStoreFunctions.Add(name);
- }
- //
- } else if (node.Op is VCExprSelectOp) {
- //
- RegisterType(node[0].Type);
- string name = SimplifyLikeExprLineariser.SelectOpName(node);
- if (!KnownSelectFunctions.Contains(name)) {
- string decl = "(DEFOP " + name;
-
- foreach (VCExpr ch in node) {
- decl += " " + TypeToString(ch.Type);
- }
- decl += " " + TypeToString(node.Type);
-
- if (CommandLineOptions.Clo.UseArrayTheory)
- decl += " :BUILTIN select";
- decl += ")";
- AddDeclaration(decl);
- KnownSelectFunctions.Add(name);
- }
- //
- } else {
- //
- VCExprBoogieFunctionOp op = node.Op as VCExprBoogieFunctionOp;
- if (op != null && !KnownFunctions.Contains(op.Func)) {
- Function f = op.Func;
- Contract.Assert(f!=null);
- string printedName = Namer.GetName(f, f.Name);
- Contract.Assert(printedName!=null);
- string decl = "(DEFOP " + SimplifyLikeExprLineariser.MakeIdPrintable(printedName);
-
- foreach (Variable v in f.InParams) {
- Contract.Assert(v!=null);
- decl += " " + TypeToString(v.TypedIdent.Type);
- RegisterType(v.TypedIdent.Type);
- }
- Contract.Assert(f.OutParams.Length == 1);
- foreach (Variable v in f.OutParams) {
- Contract.Assert(v!=null);
- decl += " " + TypeToString(v.TypedIdent.Type);
- RegisterType(v.TypedIdent.Type);
- }
-
- string builtin = ExtractBuiltin(f);
- if (builtin != null)
- decl += " :BUILTIN " + builtin;
-
- decl += ")";
-
- AddDeclaration(decl);
- KnownFunctions.Add(f);
- }
- //
- }
-
- return base.Visit(node, arg);
- }
-
- private string ExtractBuiltin(Function f) {
- Contract.Requires(f != null);
- string retVal = null;
- if (NativeBv) {
- retVal = f.FindStringAttribute("bvbuiltin");
- }
- if (retVal == null) {
- retVal = f.FindStringAttribute("builtin");
- }
- return retVal;
- }
-
- public override bool Visit(VCExprVar node, bool arg) {
- Contract.Requires(node != null);
- if (!BoundTermVars.Contains(node) && !KnownVariables.Contains(node)) {
- RegisterType(node.Type);
- string printedName = Namer.GetName(node, node.Name);
- Contract.Assert(printedName!=null);
- string decl =
- "(DEFOP " + SimplifyLikeExprLineariser.MakeIdPrintable(printedName)
- + " " + TypeToString(node.Type) + ")";
- AddDeclaration(decl);
- KnownVariables.Add(node);
- }
-
- return base.Visit(node, arg);
- }
-
- public override bool Visit(VCExprQuantifier node, bool arg) {
- Contract.Requires(node != null);
- foreach (VCExprVar v in node.BoundVars) {
- Contract.Assert(v != null);
- RegisterType(v.Type);
- }
-
- return base.Visit(node, arg);
- }
- }
-} \ No newline at end of file
diff --git a/Source/Provers/Z3/Z3.csproj b/Source/Provers/Z3/Z3.csproj
deleted file mode 100644
index e559b663..00000000
--- a/Source/Provers/Z3/Z3.csproj
+++ /dev/null
@@ -1,218 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Microsoft.Boogie.Z3</RootNamespace>
- <AssemblyName>Provers.Z3</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile>Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for Z3.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\Provers.Z3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core">
- <RequiredTargetFramework>3.5</RequiredTargetFramework>
- </Reference>
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Inspector.cs" />
- <Compile Include="Prover.cs" />
- <Compile Include="ProverInterface.cs" />
- <Compile Include="TypeDeclCollector.cs" />
- <Compile Include="..\..\version.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCExpr\VCExpr.csproj">
- <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
- <Name>VCExpr</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</Name>
- </ProjectReference>
- <ProjectReference Include="..\Simplify\Simplify.csproj">
- <Project>{FEE9F01B-9722-4A76-A24B-72A4016DFA8E}</Project>
- <Name>Simplify</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project> \ No newline at end of file
diff --git a/Source/Provers/Z3/cce.cs b/Source/Provers/Z3/cce.cs
deleted file mode 100644
index ef594484..00000000
--- a/Source/Provers/Z3/cce.cs
+++ /dev/null
@@ -1,193 +0,0 @@
-using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
- }
- //[Pure]
- //public static bool NonNullElements(VariableSeq collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
-} \ No newline at end of file
diff --git a/Source/Provers/Z3api/ContextLayer.cs b/Source/Provers/Z3api/ContextLayer.cs
index df40df3d..ad0c2239 100644
--- a/Source/Provers/Z3api/ContextLayer.cs
+++ b/Source/Provers/Z3api/ContextLayer.cs
@@ -139,8 +139,12 @@ namespace Microsoft.Boogie.Z3 {
{
case TermKind.Numeral:
var numstr = arg.GetNumeralString();
- var bignum = Basetypes.BigNum.FromString(numstr);
- res = gen.Integer(bignum);
+ if (arg.GetSort().GetSortKind() == SortKind.Int) {
+ res = gen.Integer(Basetypes.BigNum.FromString(numstr));
+ }
+ else {
+ res = gen.Real(Basetypes.BigDec.FromString(numstr));
+ }
break;
case TermKind.App:
var args = arg.GetAppArgs();
@@ -151,8 +155,14 @@ namespace Microsoft.Boogie.Z3 {
switch (arg.GetAppDecl().GetKind())
{
case DeclKind.Add:
- if (vcargs.Length == 0)
- res = gen.Integer(Basetypes.BigNum.FromInt(0));
+ if (vcargs.Length == 0) {
+ if (arg.GetSort().GetSortKind() == SortKind.Int) {
+ res = gen.Integer(Basetypes.BigNum.ZERO);
+ }
+ else {
+ res = gen.Real(Basetypes.BigDec.ZERO);
+ }
+ }
else
{
res = vcargs[0];
@@ -167,7 +177,7 @@ namespace Microsoft.Boogie.Z3 {
break;
case DeclKind.Div:
Debug.Assert(vcargs.Length == 2);
- res = gen.Function(VCExpressionGenerator.DivOp, vcargs[0], vcargs[1]);
+ res = gen.Function(VCExpressionGenerator.RealDivOp, vcargs[0], vcargs[1]);
break;
case DeclKind.Eq:
Debug.Assert(vcargs.Length == 2);
@@ -243,8 +253,22 @@ namespace Microsoft.Boogie.Z3 {
break;
case DeclKind.Uminus:
Debug.Assert(vcargs.Length == 1);
- var bigzero = Basetypes.BigNum.FromInt(0);
- res = gen.Function(VCExpressionGenerator.SubOp, gen.Integer(bigzero), vcargs[0]);
+ var argzero = null;
+ if (vcargs[0].Type.IsInt) {
+ argzero = gen.Integer(Basetypes.BigNum.ZERO);
+ }
+ else {
+ argzero = gen.Real(Basetypes.BigDec.ZERO);
+ }
+ res = gen.Function(VCExpressionGenerator.SubOp, argzero, vcargs[0]);
+ break;
+ case DeclKind.ToInt:
+ Debug.Assert(vcargs.Length == 1);
+ res = gen.Function(VCExpressionGenerator.ToIntOp, vcargs[0]);
+ break;
+ case DeclKind.ToReal:
+ Debug.Assert(vcargs.Length == 1);
+ res = gen.Function(VCExpressionGenerator.ToRealOp, vcargs[0]);
break;
case DeclKind.Uninterpreted:
var name = arg.GetAppDecl().GetDeclName();
diff --git a/Source/Provers/Z3api/TypeAdapter.cs b/Source/Provers/Z3api/TypeAdapter.cs
index e1c6de0b..879211f7 100644
--- a/Source/Provers/Z3api/TypeAdapter.cs
+++ b/Source/Provers/Z3api/TypeAdapter.cs
@@ -51,7 +51,8 @@ namespace Microsoft.Boogie.Z3
public bool Equals(BasicType x, BasicType y)
{
return (x.IsBool == y.IsBool) &&
- (x.IsInt == y.IsInt);
+ (x.IsInt == y.IsInt) &&
+ (x.IsReal == y.IsReal);
}
public int GetHashCode(BasicType basicType)
@@ -60,6 +61,8 @@ namespace Microsoft.Boogie.Z3
return 1;
else if (basicType.IsInt)
return 2;
+ else if (basicType.IsReal)
+ return 3;
else
throw new Exception("Basic Type " + basicType.ToString() + " is unkwown");
}
@@ -175,6 +178,10 @@ namespace Microsoft.Boogie.Z3
{
typeAst = z3.MkIntSort();
}
+ else if (basicType.IsReal)
+ {
+ typeAst = z3.MkRealSort();
+ }
else
throw new Exception("Unknown Basic Type " + basicType.ToString());
return typeAst;
diff --git a/Source/Provers/Z3api/VCExprVisitor.cs b/Source/Provers/Z3api/VCExprVisitor.cs
index 0605a854..e56a7950 100644
--- a/Source/Provers/Z3api/VCExprVisitor.cs
+++ b/Source/Provers/Z3api/VCExprVisitor.cs
@@ -15,6 +15,8 @@ using Microsoft.Z3;
namespace Microsoft.Boogie.Z3
{
+ using System.Numerics.BigInteger;
+
public class Z3apiExprLineariser : IVCExprVisitor<Term, LineariserOptions>
{
private Z3apiOpLineariser opLineariser = null;
@@ -110,7 +112,7 @@ namespace Microsoft.Boogie.Z3
return z3.MkSub(unwrapChildren);
}
- if (op == VCExpressionGenerator.DivOp) {
+ if (op == VCExpressionGenerator.DivOp || op == VCExpressionGenerator.RealDivOp) {
return z3.MkDiv(unwrapChildren[0], unwrapChildren[1]);
}
@@ -126,6 +128,14 @@ namespace Microsoft.Boogie.Z3
return z3.MkIte(unwrapChildren[0], unwrapChildren[1], unwrapChildren[2]);
}
+ if (op == VCExpressionGenerator.ToIntOp) {
+ return z3.MkToInt(unwrapChildren[0]);
+ }
+
+ if (op == VCExpressionGenerator.ToRealOp) {
+ return z3.MkToReal(unwrapChildren[0]);
+ }
+
throw new Exception("unhandled boogie operator");
}
@@ -139,11 +149,25 @@ namespace Microsoft.Boogie.Z3
else if (node == VCExpressionGenerator.False)
return cm.z3.MkFalse();
else if (node is VCExprIntLit)
- return cm.z3.MkNumeral(((VCExprIntLit)node).Val.ToInt, cm.z3.MkIntSort());
- else
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
+ return cm.z3.MkNumeral(((VCExprIntLit)node).Val.ToInt, cm.z3.MkIntSort());
+ else if (node is VCExprRealLit) {
+ string m = ((VCExprRealLit)node).Val.Mantissa.ToString();
+ BigInteger e = ((VCExprRealLit)node).Val.Exponent;
+ string f = BigInteger.Pow(10, e.Abs);
+
+ if (e == 0) {
+ return cm.z3.MkNumeral(m, cm.z3.MkRealSort());
+ }
+ else if (((VCExprRealLit)node).Val.Exponent > 0) {
+ return cm.z3.MkMul(cm.z3.MkNumeral(m, cm.z3.MkRealSort()), cm.z3.MkNumeral(f, cm.z3.MkRealSort()));
+ }
+ else {
+ return cm.z3.MkDiv(cm.z3.MkNumeral(m, cm.z3.MkRealSort()), cm.z3.MkNumeral(f, cm.z3.MkRealSort()));
+ }
+ }
+ else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
}
}
@@ -548,6 +572,18 @@ namespace Microsoft.Boogie.Z3
return WriteApplication(node.Op, node, options);
}
+ public Term VisitRealDivOp(VCExprNAry node, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitPowOp(VCExprNAry node, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
public Term VisitLtOp(VCExprNAry node, LineariserOptions options)
{
Contract.Requires(options != null);
@@ -590,6 +626,18 @@ namespace Microsoft.Boogie.Z3
return WriteApplication(node.Op, node, options);
}
+ public Term VisitToIntOp(VCExprNAry node, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitToRealOp(VCExprNAry node, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
public Term VisitBoogieFunctionOp(VCExprNAry node, LineariserOptions options)
{
Contract.Requires(options != null);
diff --git a/Source/Provers/Z3api/Z3api.csproj b/Source/Provers/Z3api/Z3api.csproj
index f9511dbd..bf123823 100644
--- a/Source/Provers/Z3api/Z3api.csproj
+++ b/Source/Provers/Z3api/Z3api.csproj
@@ -129,10 +129,6 @@
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
<ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
<Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
<Name>Basetypes</Name>
diff --git a/Source/VCExpr/BigLiteralAbstracter.cs b/Source/VCExpr/BigLiteralAbstracter.cs
index 7eb93541..879ab6d6 100644
--- a/Source/VCExpr/BigLiteralAbstracter.cs
+++ b/Source/VCExpr/BigLiteralAbstracter.cs
@@ -120,7 +120,7 @@ namespace Microsoft.Boogie.VCExprAST {
Contract.Ensures(Contract.Result<VCExpr>() != null);
if (lit.IsNegative)
- return Gen.Function(VCExpressionGenerator.SubOp,
+ return Gen.Function(VCExpressionGenerator.SubIOp,
Gen.Integer(BigNum.ZERO), RepresentPos(lit.Neg));
else
return RepresentPos(lit);
@@ -145,7 +145,7 @@ namespace Microsoft.Boogie.VCExprAST {
BigNum dist = lit - Literals[index - 1].Key;
if (dist < resDistance) {
resDistance = dist;
- res = Gen.Function(VCExpressionGenerator.AddOp,
+ res = Gen.Function(VCExpressionGenerator.AddIOp,
Literals[index - 1].Value, Gen.Integer(dist));
}
}
@@ -154,7 +154,7 @@ namespace Microsoft.Boogie.VCExprAST {
BigNum dist = Literals[index].Key - lit;
if (dist < resDistance) {
resDistance = dist;
- res = Gen.Function(VCExpressionGenerator.SubOp,
+ res = Gen.Function(VCExpressionGenerator.SubIOp,
Literals[index].Value, Gen.Integer(dist));
}
}
@@ -198,7 +198,7 @@ namespace Microsoft.Boogie.VCExprAST {
Contract.Requires(bExpr != null);
BigNum dist = bValue - aValue;
- VCExpr distExpr = Gen.Function(VCExpressionGenerator.SubOp, bExpr, aExpr);
+ VCExpr distExpr = Gen.Function(VCExpressionGenerator.SubIOp, bExpr, aExpr);
if (dist <= ConstantDistanceTPO)
// constants that are sufficiently close to each other are put
// into a precise relationship
diff --git a/Source/VCExpr/Boogie2VCExpr.cs b/Source/VCExpr/Boogie2VCExpr.cs
index 4e9c5c10..3035c9de 100644
--- a/Source/VCExpr/Boogie2VCExpr.cs
+++ b/Source/VCExpr/Boogie2VCExpr.cs
@@ -328,6 +328,8 @@ namespace Microsoft.Boogie.VCExprAST {
}
} else if (node.Val is BigNum) {
return Gen.Integer(node.asBigNum);
+ } else if (node.Val is BigDec) {
+ return Gen.Real(node.asBigDec);
} else if (node.Val is BvConst) {
return Gen.Bitvector((BvConst)node.Val);
} else {
@@ -339,15 +341,6 @@ namespace Microsoft.Boogie.VCExprAST {
///////////////////////////////////////////////////////////////////////////////////
- public override AIVariableExpr VisitAIVariableExpr(AIVariableExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AIVariableExpr>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
public override Expr VisitIdentifierExpr(IdentifierExpr node) {
//Contract.Requires(node != null);
Contract.Ensures(Contract.Result<Expr>() != null);
@@ -970,8 +963,20 @@ namespace Microsoft.Boogie.VCExprAST {
public VCExpr Visit(UnaryOperator unaryOperator) {
//Contract.Requires(unaryOperator != null);
Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assert(unaryOperator.Op == UnaryOperator.Opcode.Not && this.args.Count == 1);
- return Gen.Not(this.args);
+ Contract.Assert(unaryOperator.Op == UnaryOperator.Opcode.Neg || unaryOperator.Op == UnaryOperator.Opcode.Not);
+ Contract.Assert(this.args.Count == 1);
+ if (unaryOperator.Op == UnaryOperator.Opcode.Neg) {
+ VCExpr e = cce.NonNull(this.args[0]);
+ if (cce.NonNull(e.Type).IsInt) {
+ return Gen.Function(VCExpressionGenerator.SubIOp, Gen.Integer(BigNum.ZERO), e);
+ }
+ else {
+ return Gen.Function(VCExpressionGenerator.SubROp, Gen.Real(BigDec.ZERO), e);
+ }
+ }
+ else {
+ return Gen.Not(this.args);
+ }
}
public VCExpr Visit(BinaryOperator binaryOperator) {
@@ -1005,6 +1010,21 @@ namespace Microsoft.Boogie.VCExprAST {
return this.args[0];
}
+ public VCExpr Visit(ArithmeticCoercion arithCoercion) {
+ //Contract.Requires(arithCoercion != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Contract.Assert(this.args.Count == 1);
+ switch (arithCoercion.Coercion) {
+ case ArithmeticCoercion.CoercionType.ToInt:
+ return Gen.Function(VCExpressionGenerator.ToIntOp, this.args);
+ case ArithmeticCoercion.CoercionType.ToReal:
+ return Gen.Function(VCExpressionGenerator.ToRealOp, this.args);
+ default:
+ Contract.Assert(false);
+ return null;
+ }
+ }
+
public VCExpr Visit(IfThenElse ite) {
//Contract.Requires(ite != null);
Contract.Ensures(Contract.Result<VCExpr>() != null);
@@ -1021,15 +1041,42 @@ namespace Microsoft.Boogie.VCExprAST {
switch (app.Op) {
case BinaryOperator.Opcode.Add:
- return Gen.Function(VCExpressionGenerator.AddOp, args);
+ if (cce.NonNull(cce.NonNull(args[0]).Type).IsInt) {
+ return Gen.Function(VCExpressionGenerator.AddIOp, args);
+ }
+ else {
+ return Gen.Function(VCExpressionGenerator.AddROp, args);
+ }
case BinaryOperator.Opcode.Sub:
- return Gen.Function(VCExpressionGenerator.SubOp, args);
+ if (cce.NonNull(cce.NonNull(args[0]).Type).IsInt) {
+ return Gen.Function(VCExpressionGenerator.SubIOp, args);
+ }
+ else {
+ return Gen.Function(VCExpressionGenerator.SubROp, args);
+ }
case BinaryOperator.Opcode.Mul:
- return Gen.Function(VCExpressionGenerator.MulOp, args);
+ if (cce.NonNull(cce.NonNull(args[0]).Type).IsInt) {
+ return Gen.Function(VCExpressionGenerator.MulIOp, args);
+ }
+ else {
+ return Gen.Function(VCExpressionGenerator.MulROp, args);
+ }
case BinaryOperator.Opcode.Div:
- return Gen.Function(VCExpressionGenerator.DivOp, args);
+ return Gen.Function(VCExpressionGenerator.DivIOp, args);
case BinaryOperator.Opcode.Mod:
return Gen.Function(VCExpressionGenerator.ModOp, args);
+ case BinaryOperator.Opcode.RealDiv:
+ VCExpr arg0 = cce.NonNull(args[0]);
+ VCExpr arg1 = cce.NonNull(args[1]);
+ if (cce.NonNull(arg0.Type).IsInt) {
+ arg0 = Gen.Function(VCExpressionGenerator.ToRealOp, arg0);
+ }
+ if (cce.NonNull(arg1.Type).IsInt) {
+ arg1 = Gen.Function(VCExpressionGenerator.ToRealOp, arg1);
+ }
+ return Gen.Function(VCExpressionGenerator.DivROp, arg0, arg1);
+ case BinaryOperator.Opcode.Pow:
+ return Gen.Function(VCExpressionGenerator.PowOp, args);
case BinaryOperator.Opcode.Eq:
case BinaryOperator.Opcode.Iff:
// we don't distinguish between equality and equivalence at this point
diff --git a/Source/VCExpr/SimplifyLikeLineariser.cs b/Source/VCExpr/SimplifyLikeLineariser.cs
index 848fafcb..02e3adda 100644
--- a/Source/VCExpr/SimplifyLikeLineariser.cs
+++ b/Source/VCExpr/SimplifyLikeLineariser.cs
@@ -376,6 +376,13 @@ namespace Microsoft.Boogie.VCExprAST {
internal const string intMulName = "*";
internal const string intDivName = "/";
internal const string intModName = "%";
+ internal const string realAddName = "realAdd";
+ internal const string realSubName = "realSub";
+ internal const string realMulName = "realMul";
+ internal const string realDivName = "realDiv";
+ internal const string realPowName = "realPow";
+ internal const string toIntName = "toIntCoercion";
+ internal const string toRealName = "toRealCoercion";
internal void AssertAsTerm(string x, LineariserOptions options) {
Contract.Requires(options != null);
@@ -928,10 +935,16 @@ namespace Microsoft.Boogie.VCExprAST {
public bool VisitAddOp(VCExprNAry node, LineariserOptions options) {
//Contract.Requires(options != null);
//Contract.Requires(node != null);
- if (CommandLineOptions.Clo.ReflectAdd) {
- WriteTermApplication(intAddNameReflect, node, options);
- } else {
- WriteTermApplication(intAddName, node, options);
+ if (node.Type.IsInt) {
+ if (CommandLineOptions.Clo.ReflectAdd) {
+ WriteTermApplication(intAddNameReflect, node, options);
+ }
+ else {
+ WriteTermApplication(intAddName, node, options);
+ }
+ }
+ else {
+ WriteTermApplication(realAddName, node, options);
}
return true;
}
@@ -939,14 +952,24 @@ namespace Microsoft.Boogie.VCExprAST {
public bool VisitSubOp(VCExprNAry node, LineariserOptions options) {
//Contract.Requires(options != null);
//Contract.Requires(node != null);
- WriteTermApplication(intSubName, node, options);
+ if (node.Type.IsInt) {
+ WriteTermApplication(intSubName, node, options);
+ }
+ else {
+ WriteTermApplication(realSubName, node, options);
+ }
return true;
}
public bool VisitMulOp(VCExprNAry node, LineariserOptions options) {
//Contract.Requires(options != null);
//Contract.Requires(node != null);
- WriteTermApplication(intMulName, node, options);
+ if (node.Type.IsInt) {
+ WriteTermApplication(intMulName, node, options);
+ }
+ else {
+ WriteTermApplication(realMulName, node, options);
+ }
return true;
}
@@ -964,6 +987,20 @@ namespace Microsoft.Boogie.VCExprAST {
return true;
}
+ public bool VisitRealDivOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(realDivName, node, options);
+ return true;
+ }
+
+ public bool VisitPowOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(realPowName, node, options);
+ return true;
+ }
+
public bool VisitLtOp(VCExprNAry node, LineariserOptions options) {
//Contract.Requires(options != null);
//Contract.Requires(node != null);
@@ -1006,6 +1043,20 @@ namespace Microsoft.Boogie.VCExprAST {
return true;
}
+ public bool VisitToIntOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(toIntName, node, options);
+ return true;
+ }
+
+ public bool VisitToRealOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(toRealName, node, options);
+ return true;
+ }
+
public bool VisitBoogieFunctionOp(VCExprNAry node, LineariserOptions options) {
//Contract.Requires(options != null);
//Contract.Requires(node != null);
diff --git a/Source/VCExpr/TypeErasure.cs b/Source/VCExpr/TypeErasure.cs
index fb91d326..9d366c9f 100644
--- a/Source/VCExpr/TypeErasure.cs
+++ b/Source/VCExpr/TypeErasure.cs
@@ -524,6 +524,7 @@ namespace Microsoft.Boogie.TypeErasure {
public virtual void Setup() {
GetBasicTypeRepr(Type.Int);
+ GetBasicTypeRepr(Type.Real);
GetBasicTypeRepr(Type.Bool);
}
@@ -625,6 +626,7 @@ namespace Microsoft.Boogie.TypeErasure {
base.Setup();
GetTypeCasts(Type.Int);
+ GetTypeCasts(Type.Real);
GetTypeCasts(Type.Bool);
}
@@ -730,7 +732,7 @@ namespace Microsoft.Boogie.TypeErasure {
////////////////////////////////////////////////////////////////////////////
// the only types that we allow in "untyped" expressions are U,
- // Type.Int, and Type.Bool
+ // Type.Int, Type.Real, and Type.Bool
public override Type TypeAfterErasure(Type type) {
//Contract.Requires(type != null);
@@ -746,7 +748,7 @@ namespace Microsoft.Boogie.TypeErasure {
[Pure]
public override bool UnchangedType(Type type) {
//Contract.Requires(type != null);
- return type.IsInt || type.IsBool || type.IsBv || (type.IsMap && CommandLineOptions.Clo.MonomorphicArrays);
+ return type.IsInt || type.IsReal || type.IsBool || type.IsBv || (type.IsMap && CommandLineOptions.Clo.MonomorphicArrays);
}
public VCExpr Cast(VCExpr expr, Type toType) {
@@ -1143,7 +1145,7 @@ namespace Microsoft.Boogie.TypeErasure {
Contract.Requires(bindings != null);
Contract.Requires(node != null);
Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assume(node.Type == Type.Bool || node.Type == Type.Int);
+ Contract.Assume(node.Type == Type.Bool || node.Type == Type.Int || node.Type == Type.Real);
return node;
}
@@ -1360,7 +1362,7 @@ namespace Microsoft.Boogie.TypeErasure {
}
// Cast the arguments of the node to their old type if necessary and possible; otherwise use
- // their new type (int, bool, or U)
+ // their new type (int, real, bool, or U)
private VCExpr CastArgumentsToOldType(VCExprNAry node, VariableBindings bindings, int newPolarity) {
Contract.Requires(bindings != null);
Contract.Requires(node != null);
@@ -1448,19 +1450,19 @@ namespace Microsoft.Boogie.TypeErasure {
Contract.Requires((bindings != null));
Contract.Requires((node != null));
Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Int, bindings, 0);
+ return CastArguments(node, node.Type, bindings, 0);
}
public override VCExpr VisitSubOp(VCExprNAry node, VariableBindings bindings) {
Contract.Requires((bindings != null));
Contract.Requires((node != null));
Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Int, bindings, 0);
+ return CastArguments(node, node.Type, bindings, 0);
}
public override VCExpr VisitMulOp(VCExprNAry node, VariableBindings bindings) {
Contract.Requires((bindings != null));
Contract.Requires((node != null));
Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Int, bindings, 0);
+ return CastArguments(node, node.Type, bindings, 0);
}
public override VCExpr VisitDivOp(VCExprNAry node, VariableBindings bindings) {
Contract.Requires((bindings != null));
@@ -1474,29 +1476,41 @@ namespace Microsoft.Boogie.TypeErasure {
Contract.Ensures(Contract.Result<VCExpr>() != null);
return CastArguments(node, Type.Int, bindings, 0);
}
+ public override VCExpr VisitRealDivOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Real, bindings, 0);
+ }
+ public override VCExpr VisitPowOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Real, bindings, 0);
+ }
public override VCExpr VisitLtOp(VCExprNAry node, VariableBindings bindings) {
Contract.Requires((bindings != null));
Contract.Requires((node != null));
Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Int, bindings, 0);
+ return CastArgumentsToOldType(node, bindings, 0);
}
public override VCExpr VisitLeOp(VCExprNAry node, VariableBindings bindings) {
Contract.Requires((bindings != null));
Contract.Requires((node != null));
Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Int, bindings, 0);
+ return CastArgumentsToOldType(node, bindings, 0);
}
public override VCExpr VisitGtOp(VCExprNAry node, VariableBindings bindings) {
Contract.Requires((bindings != null));
Contract.Requires((node != null));
Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Int, bindings, 0);
+ return CastArgumentsToOldType(node, bindings, 0);
}
public override VCExpr VisitGeOp(VCExprNAry node, VariableBindings bindings) {
Contract.Requires((bindings != null));
Contract.Requires((node != null));
Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Int, bindings, 0);
+ return CastArgumentsToOldType(node, bindings, 0);
}
public override VCExpr VisitSubtypeOp(VCExprNAry node, VariableBindings bindings) {
Contract.Requires((bindings != null));
@@ -1504,6 +1518,18 @@ namespace Microsoft.Boogie.TypeErasure {
Contract.Ensures(Contract.Result<VCExpr>() != null);
return CastArguments(node, AxBuilder.U, bindings, 0);
}
+ public override VCExpr VisitToIntOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitToRealOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
public override VCExpr VisitBvOp(VCExprNAry node, VariableBindings bindings) {
Contract.Requires((bindings != null));
Contract.Requires((node != null));
diff --git a/Source/VCExpr/VCExpr.csproj b/Source/VCExpr/VCExpr.csproj
index 18455b6e..bd426125 100644
--- a/Source/VCExpr/VCExpr.csproj
+++ b/Source/VCExpr/VCExpr.csproj
@@ -162,10 +162,6 @@
<Compile Include="VCExprASTVisitors.cs" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
<ProjectReference Include="..\Basetypes\Basetypes.csproj">
<Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
<Name>Basetypes</Name>
diff --git a/Source/VCExpr/VCExprAST.cs b/Source/VCExpr/VCExprAST.cs
index 38541881..fcfd0041 100644
--- a/Source/VCExpr/VCExprAST.cs
+++ b/Source/VCExpr/VCExprAST.cs
@@ -49,6 +49,12 @@ namespace Microsoft.Boogie {
return new VCExprIntLit(x);
}
+ public VCExpr/*!*/ Real(BigDec x) {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return new VCExprRealLit(x);
+ }
+
public VCExpr/*!*/ Function(VCExprOp/*!*/ op,
List<VCExpr/*!*/>/*!*/ arguments,
List<Type/*!*/>/*!*/ typeArguments) {
@@ -199,7 +205,8 @@ namespace Microsoft.Boogie {
Contract.Requires(e1 != null);
Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(AddOp, e0, e1);
+ VCExprOp op = cce.NonNull(cce.NonNull(e0).Type).IsInt ? AddIOp : AddROp;
+ return Function(op, e0, e1);
}
public VCExpr/*!*/ Or(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
Contract.Requires(e0 != null);
@@ -308,11 +315,16 @@ namespace Microsoft.Boogie {
////////////////////////////////////////////////////////////////////////////////
// Further operators
- public static readonly VCExprOp AddOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp SubOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp MulOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp DivOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp AddIOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp AddROp = new VCExprNAryOp(2, Type.Real);
+ public static readonly VCExprOp SubIOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp SubROp = new VCExprNAryOp(2, Type.Real);
+ public static readonly VCExprOp MulIOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp MulROp = new VCExprNAryOp(2, Type.Real);
+ public static readonly VCExprOp DivIOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp DivROp = new VCExprNAryOp(2, Type.Real);
public static readonly VCExprOp ModOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp PowOp = new VCExprNAryOp(2, Type.Real);
public static readonly VCExprOp LtOp = new VCExprNAryOp(2, Type.Bool);
public static readonly VCExprOp LeOp = new VCExprNAryOp(2, Type.Bool);
public static readonly VCExprOp GtOp = new VCExprNAryOp(2, Type.Bool);
@@ -322,6 +334,8 @@ namespace Microsoft.Boogie {
// the type of the compared terms
public static readonly VCExprOp Subtype3Op = new VCExprNAryOp(3, Type.Bool);
public static readonly VCExprOp IfThenElseOp = new VCExprIfThenElseOp();
+ public static readonly VCExprOp ToIntOp = new VCExprNAryOp(1, Type.Int);
+ public static readonly VCExprOp ToRealOp = new VCExprNAryOp(1, Type.Real);
public static readonly VCExprOp TickleBoolOp = new VCExprCustomOp("tickleBool", 1, Type.Bool);
@@ -376,13 +390,17 @@ namespace Microsoft.Boogie {
MulOp,
DivOp,
ModOp,
+ RealDivOp,
+ PowOp,
LtOp,
LeOp,
GtOp,
GeOp,
SubtypeOp,
Subtype3Op,
- BvConcatOp
+ BvConcatOp,
+ ToIntOp,
+ ToRealOp
};
internal static Dictionary<VCExprOp/*!*/, SingletonOp>/*!*/ SingletonOpDict;
[ContractInvariantMethod]
@@ -399,17 +417,24 @@ namespace Microsoft.Boogie {
SingletonOpDict.Add(AndOp, SingletonOp.AndOp);
SingletonOpDict.Add(OrOp, SingletonOp.OrOp);
SingletonOpDict.Add(ImpliesOp, SingletonOp.ImpliesOp);
- SingletonOpDict.Add(AddOp, SingletonOp.AddOp);
- SingletonOpDict.Add(SubOp, SingletonOp.SubOp);
- SingletonOpDict.Add(MulOp, SingletonOp.MulOp);
- SingletonOpDict.Add(DivOp, SingletonOp.DivOp);
+ SingletonOpDict.Add(AddIOp, SingletonOp.AddOp);
+ SingletonOpDict.Add(AddROp, SingletonOp.AddOp);
+ SingletonOpDict.Add(SubIOp, SingletonOp.SubOp);
+ SingletonOpDict.Add(SubROp, SingletonOp.SubOp);
+ SingletonOpDict.Add(MulIOp, SingletonOp.MulOp);
+ SingletonOpDict.Add(MulROp, SingletonOp.MulOp);
+ SingletonOpDict.Add(DivIOp, SingletonOp.DivOp);
+ SingletonOpDict.Add(DivROp, SingletonOp.RealDivOp);
SingletonOpDict.Add(ModOp, SingletonOp.ModOp);
+ SingletonOpDict.Add(PowOp, SingletonOp.PowOp);
SingletonOpDict.Add(LtOp, SingletonOp.LtOp);
SingletonOpDict.Add(LeOp, SingletonOp.LeOp);
SingletonOpDict.Add(GtOp, SingletonOp.GtOp);
SingletonOpDict.Add(GeOp, SingletonOp.GeOp);
SingletonOpDict.Add(SubtypeOp, SingletonOp.SubtypeOp);
SingletonOpDict.Add(Subtype3Op, SingletonOp.Subtype3Op);
+ SingletonOpDict.Add(ToIntOp, SingletonOp.ToIntOp);
+ SingletonOpDict.Add(ToRealOp, SingletonOp.ToRealOp);
}
////////////////////////////////////////////////////////////////////////////////
@@ -810,6 +835,27 @@ namespace Microsoft.Boogie.VCExprAST {
}
}
+ public class VCExprRealLit : VCExprLiteral {
+ public readonly BigDec Val;
+ internal VCExprRealLit(BigDec val)
+ : base(Type.Real) {
+ this.Val = val;
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprRealLit)
+ return Val == ((VCExprRealLit)that).Val;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Val.GetHashCode() * 72321;
+ }
+ }
+
/////////////////////////////////////////////////////////////////////////////////
// Operator expressions with fixed arity
[ContractClassFor(typeof(VCExprNAry))]
@@ -1218,6 +1264,10 @@ namespace Microsoft.Boogie.VCExprAST {
return visitor.VisitDivOp(expr, arg);
case VCExpressionGenerator.SingletonOp.ModOp:
return visitor.VisitModOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.RealDivOp:
+ return visitor.VisitRealDivOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.PowOp:
+ return visitor.VisitPowOp(expr, arg);
case VCExpressionGenerator.SingletonOp.LtOp:
return visitor.VisitLtOp(expr, arg);
case VCExpressionGenerator.SingletonOp.LeOp:
@@ -1232,6 +1282,10 @@ namespace Microsoft.Boogie.VCExprAST {
return visitor.VisitSubtype3Op(expr, arg);
case VCExpressionGenerator.SingletonOp.BvConcatOp:
return visitor.VisitBvConcatOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.ToIntOp:
+ return visitor.VisitToIntOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.ToRealOp:
+ return visitor.VisitToRealOp(expr, arg);
default:
Contract.Assert(false);
throw new cce.UnreachableException();
diff --git a/Source/VCExpr/VCExprASTPrinter.cs b/Source/VCExpr/VCExprASTPrinter.cs
index adb3b27e..00e6fb9c 100644
--- a/Source/VCExpr/VCExprASTPrinter.cs
+++ b/Source/VCExpr/VCExprASTPrinter.cs
@@ -290,12 +290,22 @@ namespace Microsoft.Boogie.VCExprAST {
public bool VisitDivOp(VCExprNAry node, TextWriter wr) {
//Contract.Requires(wr != null);
//Contract.Requires(node != null);
- return PrintNAry("/", node, wr);
+ return PrintNAry("div", node, wr);
}
public bool VisitModOp(VCExprNAry node, TextWriter wr) {
//Contract.Requires(wr != null);
//Contract.Requires(node != null);
- return PrintNAry("%", node, wr);
+ return PrintNAry("mod", node, wr);
+ }
+ public bool VisitRealDivOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("/", node, wr);
+ }
+ public bool VisitPowOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("**", node, wr);
}
public bool VisitLtOp(VCExprNAry node, TextWriter wr) {
//Contract.Requires(wr != null);
@@ -327,6 +337,16 @@ namespace Microsoft.Boogie.VCExprAST {
//Contract.Requires(node != null);
return PrintNAry("<::", node, wr);
}
+ public bool VisitToIntOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("int", node, wr);
+ }
+ public bool VisitToRealOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("real", node, wr);
+ }
public bool VisitBoogieFunctionOp(VCExprNAry node, TextWriter wr) {
//Contract.Requires(wr != null);
//Contract.Requires(node != null);
diff --git a/Source/VCExpr/VCExprASTVisitors.cs b/Source/VCExpr/VCExprASTVisitors.cs
index 1a29bbeb..1dd1cac9 100644
--- a/Source/VCExpr/VCExprASTVisitors.cs
+++ b/Source/VCExpr/VCExprASTVisitors.cs
@@ -75,12 +75,16 @@ namespace Microsoft.Boogie.VCExprAST {
Result VisitMulOp(VCExprNAry node, Arg arg);
Result VisitDivOp(VCExprNAry node, Arg arg);
Result VisitModOp(VCExprNAry node, Arg arg);
+ Result VisitRealDivOp(VCExprNAry node, Arg arg);
+ Result VisitPowOp(VCExprNAry node, Arg arg);
Result VisitLtOp(VCExprNAry node, Arg arg);
Result VisitLeOp(VCExprNAry node, Arg arg);
Result VisitGtOp(VCExprNAry node, Arg arg);
Result VisitGeOp(VCExprNAry node, Arg arg);
Result VisitSubtypeOp(VCExprNAry node, Arg arg);
Result VisitSubtype3Op(VCExprNAry node, Arg arg);
+ Result VisitToIntOp(VCExprNAry node, Arg arg);
+ Result VisitToRealOp(VCExprNAry node, Arg arg);
Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg);
Result VisitIfThenElseOp(VCExprNAry node, Arg arg);
Result VisitCustomOp(VCExprNAry node, Arg arg);
@@ -179,6 +183,16 @@ namespace Microsoft.Boogie.VCExprAST {
throw new NotImplementedException();
}
+ public Result VisitRealDivOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitPowOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
public Result VisitLtOp(VCExprNAry node, Arg arg) {
Contract.Requires(node != null);
throw new NotImplementedException();
@@ -209,6 +223,16 @@ namespace Microsoft.Boogie.VCExprAST {
throw new NotImplementedException();
}
+ public Result VisitToIntOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitToRealOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
public Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg) {
Contract.Requires(node != null);
throw new NotImplementedException();
@@ -1427,6 +1451,14 @@ namespace Microsoft.Boogie.VCExprAST {
//Contract.Requires(node != null);
return StandardResult(node, arg);
}
+ public virtual Result VisitRealDivOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitPowOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
public virtual Result VisitLtOp(VCExprNAry node, Arg arg) {
//Contract.Requires(node != null);
return StandardResult(node, arg);
@@ -1451,6 +1483,14 @@ namespace Microsoft.Boogie.VCExprAST {
//Contract.Requires(node != null);
return StandardResult(node, arg);
}
+ public virtual Result VisitToIntOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitToRealOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
public virtual Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg) {
//Contract.Requires(node != null);
return StandardResult(node, arg);
diff --git a/Source/VCGeneration/ConditionGeneration.cs b/Source/VCGeneration/ConditionGeneration.cs
index 9837626d..795fc9ca 100644
--- a/Source/VCGeneration/ConditionGeneration.cs
+++ b/Source/VCGeneration/ConditionGeneration.cs
@@ -10,8 +10,7 @@ using System.Diagnostics;
using System.Threading;
using System.IO;
using Microsoft.Boogie;
-using Graphing;
-using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Boogie.GraphUtil;
using System.Diagnostics.Contracts;
using Microsoft.Basetypes;
using Microsoft.Boogie.VCExprAST;
diff --git a/Source/VCGeneration/GraphAlgorithms.cs b/Source/VCGeneration/GraphAlgorithms.cs
deleted file mode 100644
index 1a8ab9b1..00000000
--- a/Source/VCGeneration/GraphAlgorithms.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-using Graphing;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Linq;
-
-namespace Microsoft.Boogie {
-
-public static class GraphAlgorithms {
-
- public static Graph<Node> Dual<Node>(this Graph<Node> g, Node dummySource) {
- var exits = g.Nodes.Where(n => g.Successors(n).Count() == 0).ToList();
- if (exits.Count == 0)
- return null;
- var dual = new Graph<Node>(new HashSet<Tuple<Node, Node>>(g.Edges.Select(e => new Tuple<Node, Node>(e.Item2, e.Item1))));
- if (exits.Count == 1)
- dual.AddSource(exits[0]);
- else {
- dual.AddSource(dummySource);
- foreach (var exit in exits)
- dual.AddEdge(dummySource, exit);
- }
- return dual;
- }
-
- public static List<Tuple<Node, bool>> LoopyTopSort<Node>(this Graph<Node> g) {
- Contract.Assert(g.Reducible);
-
- int n = g.Nodes.Count;
- var nodeToNumber = new Dictionary<Node, int>(n);
- var numberToNode = new Node[n];
- var allNodes = new List<int>();
- int counter = 0;
- foreach (Node node in g.Nodes) {
- numberToNode[counter] = node;
- nodeToNumber[node] = counter;
- allNodes.Add(counter);
- counter++;
- }
-
- var loops = new List<int>[n];
- foreach (var h in g.Headers) {
- var loopNodes = new HashSet<Node>();
- foreach (var b in g.BackEdgeNodes(h))
- loopNodes.UnionWith(g.NaturalLoops(h, b));
- loops[nodeToNumber[h]] =
- new List<int>(loopNodes.Select(node => nodeToNumber[node]));
- }
-
- var successors = new List<int>[n];
- int[] incomingEdges = new int[n];
-
- foreach (var e in g.Edges) {
- Contract.Assert(e.Item1 != null);
- Contract.Assert(e.Item2 != null);
- int source = nodeToNumber[e.Item1], target = nodeToNumber[e.Item2];
- if (loops[target] == null || !loops[target].Contains(source)) {
- if (successors[source] == null)
- successors[source] = new List<int>();
- successors[source].Add(target);
- incomingEdges[target]++;
- }
- }
-
- var sortedNodes = new List<Tuple<Node, bool>>();
-
- var regionStack = new Stack<Tuple<Node, List<int>>>();
- regionStack.Push(new Tuple<Node, List<int>>(default(Node), allNodes));
-
- while (regionStack.Count != 0) {
- int rootIndex = -1;
- foreach (var i in regionStack.Peek().Item2) {
- if (incomingEdges[i] == 0) {
- rootIndex = i;
- break;
- }
- }
- if (rootIndex == -1) {
- var region = regionStack.Pop();
- if (regionStack.Count != 0)
- sortedNodes.Add(new Tuple<Node, bool>(region.Item1, true));
- continue;
- }
- incomingEdges[rootIndex] = -1;
- sortedNodes.Add(new Tuple<Node, bool>(numberToNode[rootIndex], false));
- if (successors[rootIndex] != null)
- foreach (int s in successors[rootIndex])
- incomingEdges[s]--;
- if (loops[rootIndex] != null)
- regionStack.Push(new Tuple<Node, List<int>>(numberToNode[rootIndex],
- loops[rootIndex]));
- }
-
- return sortedNodes;
- }
-
-}
-
-}
diff --git a/Source/VCGeneration/StratifiedVC.cs b/Source/VCGeneration/StratifiedVC.cs
index a2ad1bd3..6ad97141 100644
--- a/Source/VCGeneration/StratifiedVC.cs
+++ b/Source/VCGeneration/StratifiedVC.cs
@@ -7,8 +7,7 @@ using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Boogie;
-using Graphing;
-using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Boogie.GraphUtil;
using System.Diagnostics.Contracts;
using Microsoft.Basetypes;
using Microsoft.Boogie.VCExprAST;
diff --git a/Source/VCGeneration/VC.cs b/Source/VCGeneration/VC.cs
index 2ac8dc83..b13b7e35 100644
--- a/Source/VCGeneration/VC.cs
+++ b/Source/VCGeneration/VC.cs
@@ -11,8 +11,7 @@ using System.Linq;
using System.Threading;
using System.IO;
using Microsoft.Boogie;
-using Graphing;
-using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Boogie.GraphUtil;
using System.Diagnostics.Contracts;
using Microsoft.Basetypes;
using Microsoft.Boogie.VCExprAST;
@@ -2059,12 +2058,6 @@ namespace VC {
}
#endregion
- if (CommandLineOptions.Clo.DoPredication && CommandLineOptions.Clo.StratifiedInlining == 0) {
- DesugarCalls(impl);
- BlockPredicator.Predicate(program, impl);
- impl.ComputePredecessorsForBlocks();
- }
-
if (CommandLineOptions.Clo.LiveVariableAnalysis > 0) {
Microsoft.Boogie.LiveVariableAnalysis.ComputeLiveVariables(impl);
}
@@ -3039,31 +3032,6 @@ namespace VC {
}
}
- /// <summary>
- /// Simplifies the CFG of the given implementation impl by merging each
- /// basic block with a single predecessor into that predecessor if the
- /// predecessor has a single successor.
- /// </summary>
- public static void MergeBlocksIntoPredecessors(Program prog, Implementation impl) {
- var blockGraph = prog.ProcessLoops(impl);
- var predMap = new Dictionary<Block, Block>();
- foreach (var block in blockGraph.Nodes) {
- try {
- var pred = blockGraph.Predecessors(block).Single();
- if (blockGraph.Successors(pred).Single() == block) {
- Block predMapping;
- while (predMap.TryGetValue(pred, out predMapping))
- pred = predMapping;
- pred.Cmds.AddRange(block.Cmds);
- pred.TransferCmd = block.TransferCmd;
- impl.Blocks.Remove(block);
- predMap[block] = pred;
- }
- // If Single throws an exception above (i.e. not exactly one pred/succ), skip this block.
- } catch (InvalidOperationException) {}
- }
- }
-
static void DumpMap(Hashtable /*Variable->Expr*/ map) {
Contract.Requires(map != null);
foreach (DictionaryEntry de in map) {
diff --git a/Source/VCGeneration/VCGeneration.csproj b/Source/VCGeneration/VCGeneration.csproj
index 780e4891..0c98a891 100644
--- a/Source/VCGeneration/VCGeneration.csproj
+++ b/Source/VCGeneration/VCGeneration.csproj
@@ -144,29 +144,16 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
- <Compile Include="BlockPredicator.cs" />
<Compile Include="Check.cs" />
<Compile Include="ConditionGeneration.cs" />
<Compile Include="Context.cs" />
- <Compile Include="DoomCheck.cs" />
- <Compile Include="DoomedLoopUnrolling.cs" />
- <Compile Include="DoomedStrategy.cs" />
- <Compile Include="DoomErrorHandler.cs" />
- <Compile Include="GraphAlgorithms.cs" />
- <Compile Include="HasseDiagram.cs" />
<Compile Include="OrderingAxioms.cs" />
- <Compile Include="SmartBlockPredicator.cs" />
<Compile Include="StratifiedVC.cs" />
<Compile Include="VC.cs" />
- <Compile Include="VCDoomed.cs" />
<Compile Include="..\version.cs" />
<Compile Include="Wlp.cs" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
<ProjectReference Include="..\Basetypes\Basetypes.csproj">
<Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
<Name>Basetypes</Name>
@@ -217,11 +204,11 @@
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
-->
-</Project>
+</Project> \ No newline at end of file
diff --git a/Test/VSComp2010/Problem2-Invert.dfy b/Test/VSComp2010/Problem2-Invert.dfy
index 2a262d70..0f7c50c1 100644
--- a/Test/VSComp2010/Problem2-Invert.dfy
+++ b/Test/VSComp2010/Problem2-Invert.dfy
@@ -43,6 +43,7 @@ method M(N: int, A: array<int>, B: array<int>)
assert (forall i :: 0 <= i && i < N ==> A[i] == old(A[i])); // the elements of A were not changed by the loop
// it now follows from the surjectivity of A that A is the inverse of B:
assert (forall j :: 0 <= j && j < N && inImage(j) ==> 0 <= B[j] && B[j] < N && A[B[j]] == j);
+ assert (forall j,k :: 0 <= j && j < k && k < N ==> B[j] != B[k]);
}
static function inImage(i: int): bool { true } // this function is used to trigger the surjective quantification
diff --git a/Test/aitest0/Answer b/Test/aitest0/Answer
index 73a9509c..fe848aab 100644
--- a/Test/aitest0/Answer
+++ b/Test/aitest0/Answer
@@ -23,29 +23,29 @@ implementation Join(b: bool)
x := 3;
y := 4;
z := x + y;
- assume {:inferred} x == 3 && y == 4 && z == 7;
- goto Then, Else;
+ assume {:inferred} GlobalFlag && x == 3 && y == 4 && z == 7;
+ goto Then, Else;
Then:
- assume {:inferred} x == 3 && y == 4 && z == 7;
+ assume {:inferred} GlobalFlag && x == 3 && y == 4 && z == 7;
assume b <==> true;
x := x + 1;
- assume {:inferred} x == 4 && y == 4 && z == 7;
+ assume {:inferred} GlobalFlag && x == 4 && y == 4 && z == 7 && b;
goto join;
Else:
- assume {:inferred} x == 3 && y == 4 && z == 7;
+ assume {:inferred} GlobalFlag && x == 3 && y == 4 && z == 7;
assume b <==> false;
y := 4;
- assume {:inferred} x == 3 && y == 4 && z == 7;
+ assume {:inferred} GlobalFlag && x == 3 && y == 4 && z == 7 && !b;
goto join;
join:
- assume {:inferred} y == 4 && z == 7;
+ assume {:inferred} GlobalFlag && 3 <= x && x < 5 && y == 4 && z == 7;
assert y == 4;
assert z == 7;
assert GlobalFlag <==> true;
- assume {:inferred} y == 4 && z == 7;
+ assume {:inferred} GlobalFlag && 3 <= x && x < 5 && y == 4 && z == 7;
return;
}
@@ -68,20 +68,20 @@ implementation Loop()
goto test;
test: // cut point
- assume {:inferred} c == 0;
- assume {:inferred} c == 0;
+ assume {:inferred} c == 0 && 0 <= i && i < 11;
+ assume {:inferred} c == 0 && 0 <= i && i < 11;
goto Then, Else;
Then:
- assume {:inferred} c == 0;
+ assume {:inferred} c == 0 && 0 <= i && i < 11;
assume i < 10;
i := i + 1;
- assume {:inferred} c == 0;
+ assume {:inferred} c == 0 && 1 <= i && i < 11;
goto test;
Else:
- assume {:inferred} c == 0;
- assume {:inferred} c == 0;
+ assume {:inferred} c == 0 && 0 <= i && i < 11;
+ assume {:inferred} c == 0 && 0 <= i && i < 11;
return;
}
diff --git a/Test/aitest0/runtest.bat b/Test/aitest0/runtest.bat
index 1cb7a60c..b6ab77f0 100644
--- a/Test/aitest0/runtest.bat
+++ b/Test/aitest0/runtest.bat
@@ -3,5 +3,5 @@ setlocal
set BGEXE=..\..\Binaries\Boogie.exe
-%BGEXE% %* -infer:c -instrumentInfer:e -printInstrumented -noVerify constants.bpl
+%BGEXE% %* -infer:j -instrumentInfer:e -printInstrumented -noVerify constants.bpl
%BGEXE% %* -infer:j Intervals.bpl
diff --git a/Test/aitest1/Answer b/Test/aitest1/Answer
index 718e7171..bfe185e7 100644
--- a/Test/aitest1/Answer
+++ b/Test/aitest1/Answer
@@ -14,21 +14,21 @@ implementation SimpleLoop()
goto test;
test: // cut point
- assume {:inferred} 0 <= i;
- assume {:inferred} 0 <= i;
+ assume {:inferred} 0 <= i && i < 11;
+ assume {:inferred} 0 <= i && i < 11;
goto Then, Else;
Then:
- assume {:inferred} 0 <= i;
+ assume {:inferred} 0 <= i && i < 11;
assume i < 10;
i := i + 1;
- assume {:inferred} i <= 10 && 1 <= i;
+ assume {:inferred} 1 <= i && i < 11;
goto test;
Else:
- assume {:inferred} 0 <= i;
+ assume {:inferred} 0 <= i && i < 11;
assume !(i < 10);
- assume {:inferred} 10 <= i;
+ assume {:inferred} 0 <= i && i < 11;
return;
}
@@ -57,13 +57,13 @@ implementation VariableBoundLoop(n: int)
assume {:inferred} 0 <= i;
assume i < n;
i := i + 1;
- assume {:inferred} i <= n && 1 <= i;
+ assume {:inferred} 1 <= i && 1 <= n;
goto test;
Else:
assume {:inferred} 0 <= i;
assume !(i < n);
- assume {:inferred} n <= i && 0 <= i;
+ assume {:inferred} 0 <= i;
return;
}
@@ -104,7 +104,7 @@ implementation FooToo()
i := 3 * (i + 1);
i := 1 + 3 * i;
i := (i + 1) * 3;
- assume {:inferred} 1 / 3 * i == 155;
+ assume {:inferred} i == 465;
return;
}
@@ -125,7 +125,7 @@ implementation FooTooStepByStep()
i := 3 * (i + 1);
i := 1 + 3 * i;
i := (i + 1) * 3;
- assume {:inferred} 1 / 3 * i == 155;
+ assume {:inferred} i == 465;
return;
}
@@ -212,7 +212,7 @@ implementation p()
start:
assume {:inferred} true;
assume x < y;
- assume {:inferred} x + 1 <= y;
+ assume {:inferred} true;
return;
}
@@ -235,18 +235,18 @@ implementation p()
A:
assume {:inferred} true;
assume x < y;
- assume {:inferred} x + 1 <= y;
+ assume {:inferred} true;
goto B, C;
B:
- assume {:inferred} x + 1 <= y;
+ assume {:inferred} true;
x := x * x;
assume {:inferred} true;
return;
C:
- assume {:inferred} x + 1 <= y;
- assume {:inferred} x + 1 <= y;
+ assume {:inferred} true;
+ assume {:inferred} true;
return;
}
@@ -268,26 +268,26 @@ implementation p()
A:
assume {:inferred} true;
- assume 0 - 1 <= x;
+ assume -1 <= x;
assume {:inferred} -1 <= x;
goto B, E;
B:
assume {:inferred} -1 <= x;
assume x < y;
- assume {:inferred} x + 1 <= y && -1 <= x;
+ assume {:inferred} -1 <= x && 0 <= y;
goto C, E;
C:
- assume {:inferred} x + 1 <= y && -1 <= x;
+ assume {:inferred} -1 <= x && 0 <= y;
x := x * x;
- assume {:inferred} 0 <= y;
+ assume {:inferred} x < 2 && 0 <= y;
goto D, E;
D:
- assume {:inferred} 0 <= y;
+ assume {:inferred} x < 2 && 0 <= y;
x := y;
- assume {:inferred} x == y && 0 <= y;
+ assume {:inferred} 0 <= x && 0 <= y;
return;
E:
@@ -333,8 +333,8 @@ implementation p()
goto D;
D:
- assume {:inferred} 9 <= x && x <= 10;
- assume {:inferred} 9 <= x && x <= 10;
+ assume {:inferred} 9 <= x && x < 11;
+ assume {:inferred} 9 <= x && x < 11;
return;
}
@@ -363,13 +363,13 @@ implementation p()
B:
assume {:inferred} true;
assume x <= 0;
- assume {:inferred} x <= 0;
+ assume {:inferred} x < 1;
goto D;
C:
assume {:inferred} true;
assume y <= 0;
- assume {:inferred} y <= 0;
+ assume {:inferred} y < 1;
goto D;
D:
@@ -402,7 +402,7 @@ implementation foo()
i := i + 1;
i := i + 1;
j := j + 1;
- assume {:inferred} i == j + 4 && j == 1 && n == 0;
+ assume {:inferred} i == 5 && j == 1 && n == 0;
return;
}
@@ -425,20 +425,20 @@ implementation foo()
assume n >= 4;
i := 0;
j := i + 1;
- assume {:inferred} j == i + 1 && i == 0 && 4 <= n;
+ assume {:inferred} i == 0 && j == 1 && 4 <= n;
goto exit, loop0;
loop0: // cut point
- assume {:inferred} 4 <= n && 0 <= i && j == i + 1;
+ assume {:inferred} 0 <= i && 1 <= j && 4 <= n;
assume j <= n;
i := i + 1;
j := j + 1;
- assume {:inferred} j <= n + 1 && j == i + 1 && 1 <= i && 4 <= n;
+ assume {:inferred} 1 <= i && 2 <= j && 4 <= n;
goto loop0, exit;
exit:
- assume {:inferred} j <= n + 1 && 4 <= n && 0 <= i && j == i + 1;
- assume {:inferred} j <= n + 1 && 4 <= n && 0 <= i && j == i + 1;
+ assume {:inferred} 0 <= i && 1 <= j && 4 <= n;
+ assume {:inferred} 0 <= i && 1 <= j && 4 <= n;
return;
}
@@ -446,5 +446,10 @@ implementation foo()
Boogie program verifier finished with 0 verified, 0 errors
-------------------- Bound.bpl --------------------
+Bound.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Bound.bpl(8,1): start
+ Bound.bpl(14,1): LoopHead
+ Bound.bpl(22,1): AfterLoop
-Boogie program verifier finished with 1 verified, 0 errors
+Boogie program verifier finished with 0 verified, 1 error
diff --git a/Test/aitest1/runtest.bat b/Test/aitest1/runtest.bat
index 3b2c382c..6e8a7bb1 100644
--- a/Test/aitest1/runtest.bat
+++ b/Test/aitest1/runtest.bat
@@ -7,11 +7,11 @@ for %%f in (ineq.bpl Linear0.bpl Linear1.bpl Linear2.bpl
Linear3.bpl Linear4.bpl Linear5.bpl Linear6.bpl
Linear7.bpl Linear8.bpl Linear9.bpl) do (
echo -------------------- %%f --------------------
- %BGEXE% %* -infer:p -instrumentInfer:e -printInstrumented -noVerify %%f
+ %BGEXE% %* -infer:j -instrumentInfer:e -printInstrumented -noVerify %%f
)
for %%f in (Bound.bpl) do (
echo -------------------- %%f --------------------
- %BGEXE% %* -infer:p %%f
+ %BGEXE% %* -infer:j %%f
)
diff --git a/Test/aitest9/runtest.bat b/Test/aitest9/runtest.bat
index bafa6961..e66f7e2b 100644
--- a/Test/aitest9/runtest.bat
+++ b/Test/aitest9/runtest.bat
@@ -7,5 +7,5 @@ set BPLEXE=%BOOGIEDIR%\Boogie.exe
for %%f in (VarMapFixPoint.bpl TestIntervals.bpl) do (
echo.
echo -------------------- %%f --------------------
- %BPLEXE% %* %%f /infer:i
+ %BPLEXE% %* %%f /infer:j
)
diff --git a/Test/dafny0/Answer b/Test/dafny0/Answer
index 671c7c91..140f642f 100644
--- a/Test/dafny0/Answer
+++ b/Test/dafny0/Answer
@@ -332,10 +332,10 @@ Execution trace:
Definedness.dfy(86,5): Error: possible violation of function precondition
Execution trace:
(0,0): anon0
-Definedness.dfy(86,10): Error: assignment may update an object not in the enclosing context's modifies clause
+Definedness.dfy(86,10): Error: target object may be null
Execution trace:
(0,0): anon0
-Definedness.dfy(86,10): Error: target object may be null
+Definedness.dfy(86,10): Error: assignment may update an object not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
Definedness.dfy(87,10): Error: possible violation of function precondition
@@ -542,7 +542,16 @@ ResolutionErrors.dfy(309,18): Error: ghost fields are allowed only in specificat
ResolutionErrors.dfy(318,15): Error: ghost variables are allowed only in specification contexts
ResolutionErrors.dfy(343,2): Error: incorrect type of method in-parameter 1 (expected GenericClass<int>, got GenericClass<bool>)
ResolutionErrors.dfy(355,18): Error: incorrect type of datatype constructor argument (found GList<_T0>, expected GList<int>)
-48 resolution/type errors detected in ResolutionErrors.dfy
+ResolutionErrors.dfy(363,4): Error: arguments to + must be int or a collection type (instead got bool)
+ResolutionErrors.dfy(368,4): Error: all lines in a calculation must have the same type (got int after bool)
+ResolutionErrors.dfy(371,4): Error: first argument to ==> must be of type bool (instead got int)
+ResolutionErrors.dfy(371,4): Error: second argument to ==> must be of type bool (instead got int)
+ResolutionErrors.dfy(372,8): Error: first argument to ==> must be of type bool (instead got int)
+ResolutionErrors.dfy(372,8): Error: second argument to ==> must be of type bool (instead got int)
+ResolutionErrors.dfy(377,8): Error: first argument to ==> must be of type bool (instead got int)
+ResolutionErrors.dfy(377,8): Error: second argument to ==> must be of type bool (instead got int)
+ResolutionErrors.dfy(382,4): Error: print statement is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+57 resolution/type errors detected in ResolutionErrors.dfy
-------------------- ParseErrors.dfy --------------------
ParseErrors.dfy(4,19): error: a chain cannot have more than one != operator
@@ -553,7 +562,13 @@ ParseErrors.dfy(15,18): error: this operator cannot be part of a chain
ParseErrors.dfy(16,19): error: this operator cannot be part of a chain
ParseErrors.dfy(17,18): error: this operator cannot be part of a chain
ParseErrors.dfy(18,18): error: chaining not allowed from the previous operator
-8 parse errors detected in ParseErrors.dfy
+ParseErrors.dfy(46,8): error: the main operator of a calculation must be transitive
+ParseErrors.dfy(62,2): error: this operator cannot continue this calculation
+ParseErrors.dfy(63,2): error: this operator cannot continue this calculation
+ParseErrors.dfy(68,2): error: this operator cannot continue this calculation
+ParseErrors.dfy(69,2): error: this operator cannot continue this calculation
+ParseErrors.dfy(75,2): error: this operator cannot continue this calculation
+14 parse errors detected in ParseErrors.dfy
-------------------- Array.dfy --------------------
Array.dfy(10,8): Error: assignment may update an array element not in the enclosing context's modifies clause
@@ -857,19 +872,19 @@ Execution trace:
Dafny program verifier finished with 32 verified, 11 errors
-------------------- ControlStructures.dfy --------------------
-ControlStructures.dfy(5,3): Error: missing case in case statement: Blue
+ControlStructures.dfy(5,3): Error: missing case in case statement: Purple
Execution trace:
(0,0): anon0
(0,0): anon6_Else
(0,0): anon7_Else
- (0,0): anon8_Else
- (0,0): anon9_Then
-ControlStructures.dfy(5,3): Error: missing case in case statement: Purple
+ (0,0): anon8_Then
+ControlStructures.dfy(5,3): Error: missing case in case statement: Blue
Execution trace:
(0,0): anon0
(0,0): anon6_Else
(0,0): anon7_Else
- (0,0): anon8_Then
+ (0,0): anon8_Else
+ (0,0): anon9_Then
ControlStructures.dfy(14,3): Error: missing case in case statement: Purple
Execution trace:
(0,0): anon0
@@ -1305,7 +1320,7 @@ CoPredicates.dfy(30,22): Related location: Related location
Execution trace:
(0,0): anon0
-Dafny program verifier finished with 14 verified, 1 error
+Dafny program verifier finished with 12 verified, 1 error
-------------------- TypeAntecedents.dfy --------------------
TypeAntecedents.dfy(32,13): Error: assertion violation
@@ -1615,6 +1630,25 @@ TailCalls.dfy(42,12): Error: 'decreases *' is allowed only on tail-recursive met
TailCalls.dfy(64,12): Error: 'decreases *' is allowed only on tail-recursive methods
5 resolution/type errors detected in TailCalls.dfy
+-------------------- Calculations.dfy --------------------
+Calculations.dfy(3,4): Error: index out of range
+Execution trace:
+ (0,0): anon0
+ (0,0): anon11_Then
+Calculations.dfy(8,13): Error: index out of range
+Execution trace:
+ (0,0): anon0
+ (0,0): anon13_Then
+Calculations.dfy(8,17): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon13_Then
+Calculations.dfy(36,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ Calculations.dfy(31,2): anon5_Else
+
+Dafny program verifier finished with 4 verified, 4 errors
-------------------- IteratorResolution.dfy --------------------
IteratorResolution.dfy(59,11): Error: LHS of assignment does not denote a mutable field
IteratorResolution.dfy(64,18): Error: arguments must have the same type (got _T0 and int)
diff --git a/Test/dafny0/Calculations.dfy b/Test/dafny0/Calculations.dfy
new file mode 100644
index 00000000..9e44f62e
--- /dev/null
+++ b/Test/dafny0/Calculations.dfy
@@ -0,0 +1,37 @@
+method CalcTest0(s: seq<int>) {
+ calc {
+ s[0]; // error: ill-formed line
+ }
+
+ calc {
+ 2;
+ { assert s[0] == 1; } // error: ill-formed hint
+ 1 + 1;
+ }
+
+ if (|s| > 0) {
+ calc {
+ s[0]; // OK: well-formed in this context
+ { assert s[0] == s[0]; }
+ <= s[0];
+ }
+ }
+}
+
+method CalcTest1(x: int, y: int) {
+ calc {
+ x + y;
+ { assume x == 0; }
+ y;
+ }
+ assert x == 0; // OK: follows from x + y == y;
+}
+
+method CalcTest2(x: int, y: int) {
+ calc {
+ x + y;
+ { assume x == 0; }
+ y + x;
+ }
+ assert x == 0; // error: even though assumed above, is not exported by the calculation
+} \ No newline at end of file
diff --git a/Test/dafny0/CoPredicates.dfy b/Test/dafny0/CoPredicates.dfy
index 67dff91b..c5651c90 100644
--- a/Test/dafny0/CoPredicates.dfy
+++ b/Test/dafny0/CoPredicates.dfy
@@ -51,8 +51,9 @@ function U2(n: int): Stream<int>
UpwardBy2(n)
}
-ghost method Lemma2(n: int)
- ensures Even(UpwardBy2(2*n)); // this is true, but Dafny can't prove it
-{
- assert Even(U2(2*n)); // ... thanks to this lemma
-}
+// Postponed:
+//ghost method Lemma2(n: int)
+// ensures Even(UpwardBy2(2*n)); // this is true, and Dafny can prove it
+//{
+// assert Even(U2(2*n)); // ... thanks to this lemma
+//}
diff --git a/Test/dafny0/ParseErrors.dfy b/Test/dafny0/ParseErrors.dfy
index 41df50eb..9a3cc18b 100644
--- a/Test/dafny0/ParseErrors.dfy
+++ b/Test/dafny0/ParseErrors.dfy
@@ -18,3 +18,61 @@ method TestChaining1<T>(s: set<T>, t: set<T>, u: set<T>, x: T, SuperSet: set<set
ensures x in s == t; // error: 'in' is not chaining
{
}
+
+// ---------------------- calc statements -----------------------------------
+
+method TestCalc()
+{
+ calc {} // OK, empty calculations are allowed
+ calc {
+ 2 + 3; // OK, single-line calculations are allowed
+ }
+ calc {
+ 2 + 3;
+ calc { // OK: a calc statement is allowed as a sub-hint
+ 2;
+ 1 + 1;
+ }
+ calc {
+ 3;
+ 1 + 2;
+ }
+ { assert true; } // OK: multiple subhints are allowed between two lines
+ 1 + 1 + 1 + 2;
+ { assert 1 + 1 + 1 == 3; }
+ { assert true; }
+ 3 + 2;
+ }
+ calc != { // error: != is not allowed as the main operator of a calculation
+ 2 + 3;
+ 4;
+ }
+ calc { // OK, these operators are compatible
+ 2 + 3;
+ > 4;
+ >= 2 + 2;
+ }
+ calc < { // OK, these operators are compatible
+ 2 + 3;
+ == 5;
+ <= 3 + 3;
+ }
+ calc < { // error: cannot mix < and >= or >
+ 2 + 3;
+ >= 5;
+ > 2 + 2;
+ 6;
+ }
+ calc >= { // error: cannot mix >= and <= or !=
+ 2 + 3;
+ <= 5;
+ != 2 + 2;
+ 3;
+ }
+ calc { // error: cannot have more than one != per calc
+ 2 + 3;
+ != 4;
+ != 1 + 2;
+ 3;
+ }
+}
diff --git a/Test/dafny0/ResolutionErrors.dfy b/Test/dafny0/ResolutionErrors.dfy
index 274cc95a..c615c5ec 100644
--- a/Test/dafny0/ResolutionErrors.dfy
+++ b/Test/dafny0/ResolutionErrors.dfy
@@ -354,3 +354,32 @@ method MG1(l: GList, n: nat)
var t := GCons(100, GNil);
t := GCons(120, l); // error: types don't match up (List<T$0> versus List<int>)
}
+
+// ------------------- calc statements ------------------------------
+
+method TestCalc(m: int, n: int, a: bool, b: bool)
+{
+ calc {
+ a + b; // error: invalid line
+ n + m;
+ }
+ calc {
+ a && b;
+ n + m; // error: all lines must have the same type
+ }
+ calc ==> {
+ n + m; // error: ==> operator requires boolean lines
+ n + m + 1;
+ n + m + 2;
+ }
+ calc {
+ n + m;
+ n + m + 1;
+ ==> n + m + 2; // error: ==> operator requires boolean lines
+ }
+ calc {
+ n + m;
+ { print n + m; } // error: non-ghost statements are not allowed in hints
+ m + n;
+ }
+}
diff --git a/Test/dafny0/runtest.bat b/Test/dafny0/runtest.bat
index 9789e7d7..9118e388 100644
--- a/Test/dafny0/runtest.bat
+++ b/Test/dafny0/runtest.bat
@@ -24,7 +24,7 @@ for %%f in (TypeTests.dfy NatTypes.dfy SmallTests.dfy Definedness.dfy
CallStmtTests.dfy MultiSets.dfy PredExpr.dfy LetExpr.dfy
Predicates.dfy Skeletons.dfy Maps.dfy LiberalEquality.dfy
RefinementModificationChecking.dfy TailCalls.dfy
- IteratorResolution.dfy Iterators.dfy) do (
+ Calculations.dfy IteratorResolution.dfy Iterators.dfy) do (
echo.
echo -------------------- %%f --------------------
%DAFNY_EXE% /compile:0 /print:out.bpl.tmp /dprint:out.dfy.tmp %* %%f
diff --git a/Test/dafny2/Answer b/Test/dafny2/Answer
index 447f4365..2feaf6f7 100644
--- a/Test/dafny2/Answer
+++ b/Test/dafny2/Answer
@@ -54,3 +54,7 @@ Dafny program verifier finished with 3 verified, 0 errors
-------------------- MonotonicHeapstate.dfy --------------------
Dafny program verifier finished with 36 verified, 0 errors
+
+-------------------- Calculations.dfy --------------------
+
+Dafny program verifier finished with 26 verified, 0 errors
diff --git a/Test/dafny2/Calculations.dfy b/Test/dafny2/Calculations.dfy
new file mode 100644
index 00000000..8c13457b
--- /dev/null
+++ b/Test/dafny2/Calculations.dfy
@@ -0,0 +1,209 @@
+/* Lists */
+// Here are some standard definitions of List and functions on Lists
+
+datatype List<T> = Nil | Cons(T, List);
+
+function length(l: List): nat
+{
+ match l
+ case Nil => 0
+ case Cons(x, xs) => 1 + length(xs)
+}
+
+function concat(l: List, ys: List): List
+{
+ match l
+ case Nil => ys
+ case Cons(x, xs) => Cons(x, concat(xs, ys))
+}
+
+function reverse(l: List): List
+{
+ match l
+ case Nil => Nil
+ case Cons(x, xs) => concat(reverse(xs), Cons(x, Nil))
+}
+
+function revacc(l: List, acc: List): List
+{
+ match l
+ case Nil => acc
+ case Cons(x, xs) => revacc(xs, Cons(x, acc))
+}
+
+function qreverse(l: List): List
+{
+ revacc(l, Nil)
+}
+
+// Here are two lemmas about the List functions.
+
+ghost method Lemma_ConcatNil()
+ ensures forall xs :: concat(xs, Nil) == xs;
+{
+}
+
+ghost method Lemma_RevCatCommute()
+ ensures forall xs, ys, zs :: revacc(xs, concat(ys, zs)) == concat(revacc(xs, ys), zs);
+{
+}
+
+// Here is a theorem that says "qreverse" and "reverse" calculate the same result. The proof
+// is given in a calculational style. The proof is not minimal--some lines can be omitted
+// and Dafny will still fill in the details.
+
+ghost method Theorem_QReverseIsCorrect_Calc(l: List)
+ ensures qreverse(l) == reverse(l);
+{
+ calc {
+ qreverse(l);
+ // def. qreverse
+ revacc(l, Nil);
+ { Lemma_Revacc_calc(l, Nil); }
+ concat(reverse(l), Nil);
+ { Lemma_ConcatNil(); }
+ reverse(l);
+ }
+}
+
+ghost method Lemma_Revacc_calc(xs: List, ys: List)
+ ensures revacc(xs, ys) == concat(reverse(xs), ys);
+{
+ match (xs) {
+ case Nil =>
+ case Cons(x, xrest) =>
+ calc {
+ concat(reverse(xs), ys);
+ // def. reverse
+ concat(concat(reverse(xrest), Cons(x, Nil)), ys);
+ // induction hypothesis: Lemma_Revacc_calc(xrest, Cons(x, Nil))
+ concat(revacc(xrest, Cons(x, Nil)), ys);
+ { Lemma_RevCatCommute(); } // forall xs,ys,zs :: revacc(xs, concat(ys, zs)) == concat(revacc(xs, ys), zs)
+ revacc(xrest, concat(Cons(x, Nil), ys));
+ // def. concat (x2)
+ revacc(xrest, Cons(x, ys));
+ // def. revacc
+ revacc(xs, ys);
+ }
+ }
+}
+
+// Here is a version of the same proof, as it was constructed before Dafny's "calc" construct.
+
+ghost method Theorem_QReverseIsCorrect(l: List)
+ ensures qreverse(l) == reverse(l);
+{
+ assert qreverse(l)
+ == // def. qreverse
+ revacc(l, Nil);
+ Lemma_Revacc(l, Nil);
+ assert revacc(l, Nil)
+ == concat(reverse(l), Nil);
+ Lemma_ConcatNil();
+}
+
+ghost method Lemma_Revacc(xs: List, ys: List)
+ ensures revacc(xs, ys) == concat(reverse(xs), ys);
+{
+ match (xs) {
+ case Nil =>
+ case Cons(x, xrest) =>
+ assert revacc(xs, ys)
+ == // def. revacc
+ revacc(xrest, Cons(x, ys));
+
+ assert concat(reverse(xs), ys)
+ == // def. reverse
+ concat(concat(reverse(xrest), Cons(x, Nil)), ys)
+ == // induction hypothesis: Lemma3a(xrest, Cons(x, Nil))
+ concat(revacc(xrest, Cons(x, Nil)), ys);
+ Lemma_RevCatCommute(); // forall xs,ys,zs :: revacc(xs, concat(ys, zs)) == concat(revacc(xs, ys), zs)
+ assert concat(revacc(xrest, Cons(x, Nil)), ys)
+ == revacc(xrest, concat(Cons(x, Nil), ys));
+
+ assert forall g, gs :: concat(Cons(g, Nil), gs) == Cons(g, gs);
+
+ assert revacc(xrest, concat(Cons(x, Nil), ys))
+ == // the assert lemma just above
+ revacc(xrest, Cons(x, ys));
+ }
+}
+
+/* Fibonacci */
+// To further demonstrate what the "calc" construct can do, here are some proofs about the Fibonacci function.
+
+function Fib(n: nat): nat
+{
+ if n < 2 then n else Fib(n - 2) + Fib(n - 1)
+}
+
+ghost method Lemma_Fib()
+ ensures Fib(5) < 6;
+{
+ calc {
+ Fib(5);
+ Fib(4) + Fib(3);
+ calc {
+ Fib(2);
+ Fib(0) + Fib(1);
+ 0 + 1;
+ 1;
+ }
+ < 6;
+ }
+}
+
+/* List length */
+// Here are some proofs that show the use of nested calculations.
+
+ghost method Lemma_Concat_Length(xs: List, ys: List)
+ ensures length(concat(xs, ys)) == length(xs) + length(ys);
+{}
+
+ghost method Lemma_Reverse_Length(xs: List)
+ ensures length(xs) == length(reverse(xs));
+{
+ match (xs) {
+ case Nil =>
+ case Cons(x, xrest) =>
+ calc {
+ length(reverse(xs));
+ // def. reverse
+ length(concat(reverse(xrest), Cons(x, Nil)));
+ { Lemma_Concat_Length(reverse(xrest), Cons(x, Nil)); }
+ length(reverse(xrest)) + length(Cons(x, Nil));
+ // induction hypothesis
+ length(xrest) + length(Cons(x, Nil));
+ calc {
+ length(Cons(x, Nil));
+ // def. length
+ 1 + length(Nil);
+ // def. length
+ 1 + 0;
+ 1;
+ }
+ length(xrest) + 1;
+ // def. length
+ length(xs);
+ }
+ }
+}
+
+ghost method Window(xs: List, ys: List)
+ ensures length(xs) == length(ys) ==> length(reverse(xs)) == length(reverse(ys));
+{
+ calc {
+ length(xs) == length(ys) ==> length(reverse(xs)) == length(reverse(ys));
+ { if (length(xs) == length(ys)) {
+ calc {
+ length(reverse(xs));
+ { Lemma_Reverse_Length(xs); }
+ length(xs);
+ length(ys);
+ { Lemma_Reverse_Length(ys); }
+ length(reverse(ys));
+ } } }
+ length(xs) == length(ys) ==> length(reverse(xs)) == length(reverse(xs));
+ true;
+ }
+} \ No newline at end of file
diff --git a/Test/dafny2/runtest.bat b/Test/dafny2/runtest.bat
index 909f67f5..72959830 100644
--- a/Test/dafny2/runtest.bat
+++ b/Test/dafny2/runtest.bat
@@ -16,7 +16,7 @@ for %%f in (
StoreAndRetrieve.dfy
Intervals.dfy TreeFill.dfy TuringFactorial.dfy
MajorityVote.dfy SegmentSum.dfy
- MonotonicHeapstate.dfy
+ MonotonicHeapstate.dfy Calculations.dfy
) do (
echo.
echo -------------------- %%f --------------------
diff --git a/Test/inline/Answer b/Test/inline/Answer
index 655143fa..eddeb64f 100644
--- a/Test/inline/Answer
+++ b/Test/inline/Answer
@@ -566,7 +566,7 @@ implementation {:inline 1} find(A: [int]int, size: int, x: int) returns (ret: in
var b: bool;
anon0:
- ret := 0 - 1;
+ ret := -1;
b := false;
found := b;
i := 0;
@@ -659,7 +659,7 @@ implementation main(x: int)
goto inline$find$0$anon0;
inline$find$0$anon0:
- inline$find$0$ret := 0 - 1;
+ inline$find$0$ret := -1;
inline$find$0$b := false;
inline$find$0$found := inline$find$0$b;
inline$find$0$i := 0;
@@ -756,7 +756,7 @@ implementation {:inline 1} find(A: [int]int, size: int, x: int) returns (ret: in
var inline$check$0$ret: bool;
anon0:
- ret := 0 - 1;
+ ret := -1;
b := false;
found := b;
i := 0;
diff --git a/Test/livevars/bla1.bpl b/Test/livevars/bla1.bpl
index 2854e5df..12ccc44a 100644
--- a/Test/livevars/bla1.bpl
+++ b/Test/livevars/bla1.bpl
@@ -471,7 +471,7 @@ function {:inline true} INT_NEQ(x:int, y:int) returns (bool) {x != y}
function {:inline true} INT_ADD(x:int, y:int) returns (int) {x + y}
function {:inline true} INT_SUB(x:int, y:int) returns (int) {x - y}
function {:inline true} INT_MULT(x:int, y:int) returns (int) {x * y}
-function {:inline true} INT_DIV(x:int, y:int) returns (int) {x / y}
+function {:inline true} INT_DIV(x:int, y:int) returns (int) {x div y}
function {:inline true} INT_LT(x:int, y:int) returns (bool) {x < y}
function {:inline true} INT_ULT(x:int, y:int) returns (bool) {x < y}
function {:inline true} INT_LEQ(x:int, y:int) returns (bool) {x <= y}
diff --git a/Test/livevars/daytona_bug2_ioctl_example_1.bpl b/Test/livevars/daytona_bug2_ioctl_example_1.bpl
index 1decba12..ae8ff08c 100644
--- a/Test/livevars/daytona_bug2_ioctl_example_1.bpl
+++ b/Test/livevars/daytona_bug2_ioctl_example_1.bpl
@@ -510,7 +510,7 @@ function {:inline true} INT_NEQ(x:int, y:int) returns (bool) {x != y}
function {:inline true} INT_ADD(x:int, y:int) returns (int) {x + y}
function {:inline true} INT_SUB(x:int, y:int) returns (int) {x - y}
function {:inline true} INT_MULT(x:int, y:int) returns (int) {x * y}
-function {:inline true} INT_DIV(x:int, y:int) returns (int) {x / y}
+function {:inline true} INT_DIV(x:int, y:int) returns (int) {x div y}
function {:inline true} INT_LT(x:int, y:int) returns (bool) {x < y}
function {:inline true} INT_ULT(x:int, y:int) returns (bool) {x < y}
function {:inline true} INT_LEQ(x:int, y:int) returns (bool) {x <= y}
diff --git a/Test/livevars/daytona_bug2_ioctl_example_2.bpl b/Test/livevars/daytona_bug2_ioctl_example_2.bpl
index 0b49364b..44e51827 100644
--- a/Test/livevars/daytona_bug2_ioctl_example_2.bpl
+++ b/Test/livevars/daytona_bug2_ioctl_example_2.bpl
@@ -521,7 +521,7 @@ function {:inline true} INT_NEQ(x:int, y:int) returns (bool) {x != y}
function {:inline true} INT_ADD(x:int, y:int) returns (int) {x + y}
function {:inline true} INT_SUB(x:int, y:int) returns (int) {x - y}
function {:inline true} INT_MULT(x:int, y:int) returns (int) {x * y}
-function {:inline true} INT_DIV(x:int, y:int) returns (int) {x / y}
+function {:inline true} INT_DIV(x:int, y:int) returns (int) {x div y}
function {:inline true} INT_LT(x:int, y:int) returns (bool) {x < y}
function {:inline true} INT_ULT(x:int, y:int) returns (bool) {x < y}
function {:inline true} INT_LEQ(x:int, y:int) returns (bool) {x <= y}
diff --git a/Test/livevars/stack_overflow.bpl b/Test/livevars/stack_overflow.bpl
index 242acd65..fae3e863 100644
--- a/Test/livevars/stack_overflow.bpl
+++ b/Test/livevars/stack_overflow.bpl
@@ -831,7 +831,7 @@ function {:inline true} INT_NEQ(x:int, y:int) returns (bool) {x != y}
function {:inline true} INT_ADD(x:int, y:int) returns (int) {x + y}
function {:inline true} INT_SUB(x:int, y:int) returns (int) {x - y}
function {:inline true} INT_MULT(x:int, y:int) returns (int) {x * y}
-function {:inline true} INT_DIV(x:int, y:int) returns (int) {x / y}
+function {:inline true} INT_DIV(x:int, y:int) returns (int) {x div y}
function {:inline true} INT_LT(x:int, y:int) returns (bool) {x < y}
function {:inline true} INT_ULT(x:int, y:int) returns (bool) {x < y}
function {:inline true} INT_LEQ(x:int, y:int) returns (bool) {x <= y}
diff --git a/Test/prover/Answer b/Test/prover/Answer
index 1ca6407c..688e6e6a 100644
--- a/Test/prover/Answer
+++ b/Test/prover/Answer
@@ -4,7 +4,7 @@
z3mutl.bpl(20,5): Error BP5001: This assertion might not hold.
Execution trace:
z3mutl.bpl(5,1): start
- z3mutl.bpl(14,1): L3
+ z3mutl.bpl(8,1): L1
z3mutl.bpl(20,1): L5
z3mutl.bpl(20,5): Error BP5001: This assertion might not hold.
Execution trace:
@@ -14,7 +14,7 @@ Execution trace:
z3mutl.bpl(20,5): Error BP5001: This assertion might not hold.
Execution trace:
z3mutl.bpl(5,1): start
- z3mutl.bpl(8,1): L1
+ z3mutl.bpl(14,1): L3
z3mutl.bpl(20,1): L5
Boogie program verifier finished with 0 verified, 3 errors
@@ -24,19 +24,19 @@ EQ_v2.Eval__v4.Eval_out.bpl(2101,5): Error BP5003: A postcondition might not hol
EQ_v2.Eval__v4.Eval_out.bpl(1715,3): Related location: This is the postcondition that might not hold.
Execution trace:
EQ_v2.Eval__v4.Eval_out.bpl(1786,3): AA_INSTR_EQ_BODY
- EQ_v2.Eval__v4.Eval_out.bpl(1862,3): inline$v2.Eval$0$label_11_case_2#2
+ EQ_v2.Eval__v4.Eval_out.bpl(1875,3): inline$v2.Eval$0$label_11_case_1#2
EQ_v2.Eval__v4.Eval_out.bpl(1894,3): inline$v2.Eval$0$label_12#2
- EQ_v2.Eval__v4.Eval_out.bpl(1989,3): inline$v4.Eval$0$label_11_case_2#2
- EQ_v2.Eval__v4.Eval_out.bpl(2011,3): inline$v4.Eval$0$label_14_true#2
+ EQ_v2.Eval__v4.Eval_out.bpl(2032,3): inline$v4.Eval$0$label_11_case_1#2
+ EQ_v2.Eval__v4.Eval_out.bpl(2054,3): inline$v4.Eval$0$label_13_true#2
EQ_v2.Eval__v4.Eval_out.bpl(2081,3): inline$v4.Eval$0$label_12#2
EQ_v2.Eval__v4.Eval_out.bpl(2101,5): Error BP5003: A postcondition might not hold on this return path.
EQ_v2.Eval__v4.Eval_out.bpl(1715,3): Related location: This is the postcondition that might not hold.
Execution trace:
EQ_v2.Eval__v4.Eval_out.bpl(1786,3): AA_INSTR_EQ_BODY
- EQ_v2.Eval__v4.Eval_out.bpl(1875,3): inline$v2.Eval$0$label_11_case_1#2
+ EQ_v2.Eval__v4.Eval_out.bpl(1862,3): inline$v2.Eval$0$label_11_case_2#2
EQ_v2.Eval__v4.Eval_out.bpl(1894,3): inline$v2.Eval$0$label_12#2
- EQ_v2.Eval__v4.Eval_out.bpl(2032,3): inline$v4.Eval$0$label_11_case_1#2
- EQ_v2.Eval__v4.Eval_out.bpl(2054,3): inline$v4.Eval$0$label_13_true#2
+ EQ_v2.Eval__v4.Eval_out.bpl(1989,3): inline$v4.Eval$0$label_11_case_2#2
+ EQ_v2.Eval__v4.Eval_out.bpl(2011,3): inline$v4.Eval$0$label_14_true#2
EQ_v2.Eval__v4.Eval_out.bpl(2081,3): inline$v4.Eval$0$label_12#2
EQ_v2.Eval__v4.Eval_out.bpl(2152,5): Error BP5003: A postcondition might not hold on this return path.
EQ_v2.Eval__v4.Eval_out.bpl(2120,3): Related location: This is the postcondition that might not hold.
diff --git a/Test/prover/EQ_v2.Eval__v4.Eval_out.bpl b/Test/prover/EQ_v2.Eval__v4.Eval_out.bpl
index e4da94f4..e53e00b4 100644
--- a/Test/prover/EQ_v2.Eval__v4.Eval_out.bpl
+++ b/Test/prover/EQ_v2.Eval__v4.Eval_out.bpl
@@ -382,7 +382,7 @@ axiom (forall x: int, y: int :: { v4.INT_SUB(x, y): int } v4.INT_SUB(x, y): int
axiom (forall x: int, y: int :: { v4.INT_MULT(x, y): int } v4.INT_MULT(x, y): int == x * y);
-axiom (forall x: int, y: int :: { v4.INT_DIV(x, y): int } v4.INT_DIV(x, y): int == x / y);
+axiom (forall x: int, y: int :: { v4.INT_DIV(x, y): int } v4.INT_DIV(x, y): int == x div y);
axiom (forall x: int, y: int :: { v4.INT_LT(x, y): bool } v4.INT_LT(x, y): bool <==> x < y);
@@ -1173,7 +1173,7 @@ axiom (forall x: int, y: int :: { v4.INT_SUB(x, y): int } v4.INT_SUB(x, y): int
axiom (forall x: int, y: int :: { v4.INT_MULT(x, y): int } v4.INT_MULT(x, y): int == x * y);
-axiom (forall x: int, y: int :: { v4.INT_DIV(x, y): int } v4.INT_DIV(x, y): int == x / y);
+axiom (forall x: int, y: int :: { v4.INT_DIV(x, y): int } v4.INT_DIV(x, y): int == x div y);
axiom (forall x: int, y: int :: { v4.INT_LT(x, y): bool } v4.INT_LT(x, y): bool <==> x < y);
diff --git a/Test/test0/Answer b/Test/test0/Answer
index 51a139b7..0eda9e2e 100644
--- a/Test/test0/Answer
+++ b/Test/test0/Answer
@@ -34,6 +34,12 @@ const y: int;
const z: int;
+const r: real;
+
+const s: real;
+
+const t: real;
+
const P: bool;
const Q: bool;
@@ -48,10 +54,44 @@ axiom x * y * z == x * y * z;
axiom x * y * z * x == x * y * z;
+axiom x div y div z == x div (y div z);
+
+axiom x div y div (z div x) == x div y div z;
+
+axiom x + y mod z == y mod z + x;
+
+axiom (x + y) mod z == x mod z + y mod z;
+
axiom x / y / z == x / (y / z);
axiom x / y / (z / x) == x / y / z;
+axiom x / s / z == x / (s / z);
+
+axiom x / s / (z / x) == x / s / z;
+
+axiom r / s / t == r / (s / t);
+
+axiom r / s / (t / r) == r / s / t;
+
+axiom r * s / t == r * s / t;
+
+axiom r / s * t == r / s * t;
+
+axiom (r * s) ** t == r ** t * s ** t;
+
+axiom r ** (s + t) == r ** s * r ** t;
+
+axiom int(real(x)) == x;
+
+axiom r >= 0e0 ==> real(int(r)) <= r;
+
+axiom int(0e0 - 2e-2) == 0;
+
+axiom int(0e0 - 35e0) == -35;
+
+axiom int(27e-1) == 2;
+
axiom x - y - z == x - (y - z);
axiom x - y - (z - x) == x - y - z;
diff --git a/Test/test0/BadLabels1.bpl b/Test/test0/BadLabels1.bpl
index 28fb47b8..c040ce26 100644
--- a/Test/test0/BadLabels1.bpl
+++ b/Test/test0/BadLabels1.bpl
@@ -28,7 +28,7 @@ procedure P1(y: int)
{
K:
goto A;
- if (y % 2 == 0) {
+ if (y mod 2 == 0) {
goto L;
M:
}
diff --git a/Test/test0/ModifiedBag.bpl b/Test/test0/ModifiedBag.bpl
index cb69aa5f..5fffc20a 100644
--- a/Test/test0/ModifiedBag.bpl
+++ b/Test/test0/ModifiedBag.bpl
@@ -1,5 +1,5 @@
// ----------- BEGIN PRELUDE
-type real;
+
type elements;
diff --git a/Test/test0/PrettyPrint.bpl b/Test/test0/PrettyPrint.bpl
index a1f941d8..7e4a9ce7 100644
--- a/Test/test0/PrettyPrint.bpl
+++ b/Test/test0/PrettyPrint.bpl
@@ -1,6 +1,9 @@
const x: int;
const y: int;
const z: int;
+const r: real;
+const s: real;
+const t: real;
const P: bool;
const Q: bool;
const R: bool;
@@ -11,8 +14,30 @@ axiom (x * y) + z == (x + y) * z;
axiom x * y * z == (x * (y * z));
axiom (x * y) * (z * x) == (x * y) * z;
+axiom x div y div z == (x div (y div z));
+axiom (x div y) div (z div x) == (x div y) div z;
+
+axiom x + y mod z == ((y mod z) + x);
+axiom (x + y) mod z == (x mod z) + (y mod z);
+
axiom x / y / z == (x / (y / z));
axiom (x / y) / (z / x) == (x / y) / z;
+axiom x / s / z == (x / (s / z));
+axiom (x / s) / (z / x) == (x / s) / z;
+axiom r / s / t == (r / (s / t));
+axiom (r / s) / (t / r) == (r / s) / t;
+
+axiom ((r * s) / t) == r * s / t;
+axiom ((r / s) * t) == (r / s) * t;
+
+axiom (r * s) ** t == (r ** t) * (s ** t);
+axiom r ** (s + t) == r ** s * r ** t;
+
+axiom int(real(x)) == x;
+axiom r >= 0.0 ==> real(int(r)) <= r;
+axiom int(0e-3 - 0.02) == 0;
+axiom int(0e2 - 3.5e1) == -35;
+axiom int(27e-1) == 2;
axiom x - y - z == (x - (y - z));
axiom (x - y) - (z - x) == (x - y) - z;
diff --git a/Test/test0/Prog0.bpl b/Test/test0/Prog0.bpl
index ac87476f..79a4d2ab 100644
--- a/Test/test0/Prog0.bpl
+++ b/Test/test0/Prog0.bpl
@@ -1,5 +1,5 @@
// BoogiePL Examples
-type real;
+
type elements;
var x:int; var y:real; var z:ref; // Variables
diff --git a/Test/test1/Answer b/Test/test1/Answer
index a8b73b53..94bf2d9a 100644
--- a/Test/test1/Answer
+++ b/Test/test1/Answer
@@ -145,3 +145,22 @@ Lambda.bpl(12,8): Error: the type variable T does not occur in types of the lamb
Lambda.bpl(12,2): Error: mismatched types in assignment command (cannot assign <T>[int]int to [int]int)
Lambda.bpl(18,27): Error: invalid argument types (bool and int) to binary operator +
5 type checking errors detected in Lambda.bpl
+IntReal.bpl(5,8): Error: invalid argument types (int and real) to binary operator >=
+IntReal.bpl(6,8): Error: invalid argument types (int and real) to binary operator <=
+IntReal.bpl(7,8): Error: invalid argument types (int and real) to binary operator <
+IntReal.bpl(8,8): Error: invalid argument types (int and real) to binary operator >
+IntReal.bpl(10,9): Error: invalid argument types (int and real) to binary operator ==
+IntReal.bpl(11,8): Error: invalid argument types (int and real) to binary operator +
+IntReal.bpl(12,8): Error: invalid argument types (int and real) to binary operator -
+IntReal.bpl(13,8): Error: invalid argument types (int and real) to binary operator *
+IntReal.bpl(14,8): Error: invalid argument types (int and real) to binary operator div
+IntReal.bpl(15,8): Error: invalid argument types (int and real) to binary operator mod
+IntReal.bpl(17,12): Error: invalid argument types (real and int) to binary operator ==
+IntReal.bpl(23,8): Error: invalid argument types (int and real) to binary operator **
+IntReal.bpl(27,14): Error: invalid argument types (real and int) to binary operator ==
+IntReal.bpl(29,13): Error: invalid argument types (int and real) to binary operator ==
+IntReal.bpl(32,6): Error: argument type int does not match expected type real
+IntReal.bpl(33,6): Error: argument type real does not match expected type int
+IntReal.bpl(45,8): Error: invalid argument types (real and int) to binary operator div
+IntReal.bpl(46,8): Error: invalid argument types (real and int) to binary operator mod
+18 type checking errors detected in IntReal.bpl \ No newline at end of file
diff --git a/Test/test1/IntReal.bpl b/Test/test1/IntReal.bpl
new file mode 100644
index 00000000..976fc864
--- /dev/null
+++ b/Test/test1/IntReal.bpl
@@ -0,0 +1,48 @@
+const i: int;
+const r: real;
+
+axiom i == 0;
+axiom i >= 0.0; // type error
+axiom i <= 0.0e0; // type error
+axiom i < 0.0e-0; // type error
+axiom i > 0.0e20; // type error
+
+axiom -i == r; // type error
+axiom i + r == 0.0; // type error
+axiom i - r == 0.0; // type error
+axiom i * r == 0.0; // type error
+axiom i div r == 0; // type error
+axiom i mod r == 0; // type error
+
+axiom i / i == 0; // type error
+axiom i / i == 0.0;
+axiom i / r == 0.0;
+axiom r / i == 0.0;
+axiom r / r == 0.0;
+
+axiom i ** r == 0.0; // type error
+axiom r ** r == 0.0;
+
+axiom real(i) == 0.0;
+axiom real(i) == i; // type error
+axiom int(r) == 0;
+axiom int(r) == r; // type error
+axiom int(real(i)) == i;
+axiom real(int(r)) == r;
+axiom int(int(r)) == i; // type error
+axiom real(real(i)) == r; // type error
+
+axiom i == 0;
+axiom real(i) >= 0.0;
+axiom real(i) <= 0.0e0;
+axiom r < 0.0e-0;
+axiom r > 0.0e20;
+
+axiom -r == real(i);
+axiom real(i) + r == 0.0;
+axiom r - real(0) == 0.0;
+axiom r * r == 0.0;
+axiom r div 0 == 0; // type error
+axiom r mod 0 == 0; // type error
+
+axiom r ** r == 0.0;
diff --git a/Test/test1/runtest.bat b/Test/test1/runtest.bat
index 979c36e4..149e6dc9 100644
--- a/Test/test1/runtest.bat
+++ b/Test/test1/runtest.bat
@@ -19,3 +19,4 @@ rem set BGEXE=mono ..\..\Binaries\Boogie.exe
%BGEXE% %* /noVerify FunBody.bpl
%BGEXE% %* /noVerify IfThenElse0.bpl
%BGEXE% %* /noVerify Lambda.bpl
+%BGEXE% %* /noVerify IntReal.bpl
diff --git a/Test/test15/Answer b/Test/test15/Answer
index 3361b320..915f63e8 100644
--- a/Test/test15/Answer
+++ b/Test/test15/Answer
@@ -1,22 +1,24 @@
-------------------- NullInModel --------------------
*** MODEL
-%lbl%@46 -> false
-%lbl%+23 -> true
-%lbl%+36 -> true
-boolType -> T@T!val!1
+%lbl%@45 -> false
+%lbl%+24 -> true
+%lbl%+35 -> true
+boolType -> T@T!val!2
intType -> T@T!val!0
null -> T@U!val!0
-refType -> T@T!val!2
+realType -> T@T!val!1
+refType -> T@T!val!3
s -> T@U!val!0
type -> {
- T@U!val!0 -> T@T!val!2
- else -> T@T!val!2
+ T@U!val!0 -> T@T!val!3
+ else -> T@T!val!3
}
Ctor -> {
T@T!val!0 -> 0
T@T!val!1 -> 1
T@T!val!2 -> 2
+ T@T!val!3 -> 3
else -> 0
}
tickleBool -> {
@@ -33,15 +35,17 @@ Boogie program verifier finished with 0 verified, 1 error
-------------------- IntInModel --------------------
*** MODEL
-%lbl%@38 -> false
-%lbl%+22 -> true
-%lbl%+28 -> true
-boolType -> T@T!val!1
+%lbl%@37 -> false
+%lbl%+23 -> true
+%lbl%+27 -> true
+boolType -> T@T!val!2
i -> 0
intType -> T@T!val!0
+realType -> T@T!val!1
Ctor -> {
T@T!val!0 -> 0
T@T!val!1 -> 1
+ T@T!val!2 -> 2
else -> 0
}
tickleBool -> {
@@ -58,27 +62,29 @@ Boogie program verifier finished with 0 verified, 1 error
-------------------- ModelTest --------------------
*** MODEL
-%lbl%@181 -> false
-%lbl%+118 -> true
-%lbl%+63 -> true
-boolType -> T@T!val!1
+%lbl%@145 -> false
+%lbl%+64 -> true
+%lbl%+82 -> true
+boolType -> T@T!val!2
i@0 -> 1
intType -> T@T!val!0
j@0 -> 2
j@1 -> 3
j@2 -> 4
r -> T@U!val!1
-refType -> T@T!val!2
+realType -> T@T!val!1
+refType -> T@T!val!3
s -> T@U!val!0
type -> {
- T@U!val!0 -> T@T!val!2
- T@U!val!1 -> T@T!val!2
- else -> T@T!val!2
+ T@U!val!0 -> T@T!val!3
+ T@U!val!1 -> T@T!val!3
+ else -> T@T!val!3
}
Ctor -> {
T@T!val!0 -> 0
T@T!val!1 -> 1
T@T!val!2 -> 2
+ T@T!val!3 -> 3
else -> 0
}
tickleBool -> {
@@ -114,37 +120,38 @@ Execution trace:
CaptureState.bpl(16,5): anon4_Then
CaptureState.bpl(24,5): anon3
*** MODEL
-%lbl%@335 -> false
-%lbl%+111 -> true
-%lbl%+113 -> true
-%lbl%+117 -> true
-%lbl%+190 -> true
+%lbl%@291 -> false
+%lbl%+112 -> true
+%lbl%+114 -> true
+%lbl%+118 -> true
+%lbl%+146 -> true
@MV_state_const -> 6
-boolType -> T@T!val!1
+boolType -> T@T!val!2
F -> T@U!val!2
-FieldNameType -> T@T!val!3
+FieldNameType -> T@T!val!4
Heap -> T@U!val!0
intType -> T@T!val!0
m -> **m
-m@0 -> -2
-m@2 -> -1
-m@3 -> -1
+m@0 -> -451
+m@2 -> -450
+m@3 -> -450
r -> **r
-r@0 -> -2
-RefType -> T@T!val!2
+r@0 -> -900
+realType -> T@T!val!1
+RefType -> T@T!val!3
this -> T@U!val!1
-x@@4 -> 797
+x@@5 -> 0
y@@1 -> **y@@1
int_2_U -> {
- -2 -> -2
- else -> -2
+ -451 -> -451
+ else -> -451
}
type -> {
- T@U!val!0 -> T@T!val!4
- T@U!val!1 -> T@T!val!2
- T@U!val!2 -> T@T!val!3
- -2 -> T@T!val!0
- else -> T@T!val!4
+ T@U!val!0 -> T@T!val!5
+ T@U!val!1 -> T@T!val!3
+ T@U!val!2 -> T@T!val!4
+ -451 -> T@T!val!0
+ else -> T@T!val!5
}
@MV_state -> {
6 0 -> true
@@ -156,26 +163,27 @@ type -> {
Ctor -> {
T@T!val!0 -> 0
T@T!val!1 -> 1
- T@T!val!2 -> 3
+ T@T!val!2 -> 2
T@T!val!3 -> 4
- T@T!val!4 -> 2
+ T@T!val!4 -> 5
+ T@T!val!5 -> 3
else -> 0
}
[3] -> {
- T@U!val!0 T@U!val!1 T@U!val!2 -> -2
- else -> -2
+ T@U!val!0 T@U!val!1 T@U!val!2 -> -451
+ else -> -451
}
U_2_int -> {
- -2 -> -2
- else -> -2
+ -451 -> -451
+ else -> -451
}
MapType0TypeInv1 -> {
- T@T!val!4 -> T@T!val!3
- else -> T@T!val!3
+ T@T!val!5 -> T@T!val!4
+ else -> T@T!val!4
}
MapType0TypeInv0 -> {
- T@T!val!4 -> T@T!val!2
- else -> T@T!val!2
+ T@T!val!5 -> T@T!val!3
+ else -> T@T!val!3
}
tickleBool -> {
true -> true
@@ -183,17 +191,17 @@ tickleBool -> {
else -> true
}
MapType0Type -> {
- T@T!val!2 T@T!val!3 T@T!val!0 -> T@T!val!4
- else -> T@T!val!4
+ T@T!val!3 T@T!val!4 T@T!val!0 -> T@T!val!5
+ else -> T@T!val!5
}
MapType0TypeInv2 -> {
- T@T!val!4 -> T@T!val!0
+ T@T!val!5 -> T@T!val!0
else -> T@T!val!0
}
*** STATE <initial>
Heap -> T@U!val!0
this -> T@U!val!1
- x -> 797
+ x -> 0
y -> **y@@1
r -> **r
m -> **m
@@ -201,13 +209,13 @@ MapType0TypeInv2 -> {
*** STATE top
*** END_STATE
*** STATE then
- m -> -2
+ m -> -451
*** END_STATE
*** STATE postUpdate0
- m -> -1
+ m -> -450
*** END_STATE
*** STATE end
- r -> -2
+ r -> -900
m -> 7
*** END_STATE
*** END_MODEL
diff --git a/Test/test2/strings-no-where.bpl b/Test/test2/strings-no-where.bpl
index ff723db2..6aee18ea 100644
--- a/Test/test2/strings-no-where.bpl
+++ b/Test/test2/strings-no-where.bpl
@@ -1,4 +1,4 @@
-type real;
+
type elements;
@@ -330,23 +330,23 @@ function #shl(int, int) returns (int);
function #shr(int, int) returns (int);
-axiom (forall x: int, y: int :: { x % y } { x / y } x % y == x - x / y * y);
+axiom (forall x: int, y: int :: { x mod y } { x div y } x mod y == x - x div y * y);
-axiom (forall x: int, y: int :: { x % y } 0 <= x && 0 < y ==> 0 <= x % y && x % y < y);
+axiom (forall x: int, y: int :: { x mod y } 0 <= x && 0 < y ==> 0 <= x mod y && x mod y < y);
-axiom (forall x: int, y: int :: { x % y } 0 <= x && y < 0 ==> 0 <= x % y && x % y < 0 - y);
+axiom (forall x: int, y: int :: { x mod y } 0 <= x && y < 0 ==> 0 <= x mod y && x mod y < 0 - y);
-axiom (forall x: int, y: int :: { x % y } x <= 0 && 0 < y ==> 0 - y < x % y && x % y <= 0);
+axiom (forall x: int, y: int :: { x mod y } x <= 0 && 0 < y ==> 0 - y < x mod y && x mod y <= 0);
-axiom (forall x: int, y: int :: { x % y } x <= 0 && y < 0 ==> y < x % y && x % y <= 0);
+axiom (forall x: int, y: int :: { x mod y } x <= 0 && y < 0 ==> y < x mod y && x mod y <= 0);
-axiom (forall x: int, y: int :: { (x + y) % y } 0 <= x && 0 <= y ==> (x + y) % y == x % y);
+axiom (forall x: int, y: int :: { (x + y) mod y } 0 <= x && 0 <= y ==> (x + y) mod y == x mod y);
-axiom (forall x: int, y: int :: { (y + x) % y } 0 <= x && 0 <= y ==> (y + x) % y == x % y);
+axiom (forall x: int, y: int :: { (y + x) mod y } 0 <= x && 0 <= y ==> (y + x) mod y == x mod y);
-axiom (forall x: int, y: int :: { (x - y) % y } 0 <= x - y && 0 <= y ==> (x - y) % y == x % y);
+axiom (forall x: int, y: int :: { (x - y) mod y } 0 <= x - y && 0 <= y ==> (x - y) mod y == x mod y);
-axiom (forall a: int, b: int, d: int :: { a % d,b % d } 2 <= d && a % d == b % d && a < b ==> a + d <= b);
+axiom (forall a: int, b: int, d: int :: { a mod d,b mod d } 2 <= d && a mod d == b mod d && a < b ==> a + d <= b);
axiom (forall i: int :: { #shl(i, 0) } #shl(i, 0) == i);
@@ -354,7 +354,7 @@ axiom (forall i: int, j: int :: 0 <= j ==> #shl(i, j + 1) == #shl(i, j) * 2);
axiom (forall i: int :: { #shr(i, 0) } #shr(i, 0) == i);
-axiom (forall i: int, j: int :: 0 <= j ==> #shr(i, j + 1) == #shr(i, j) / 2);
+axiom (forall i: int, j: int :: 0 <= j ==> #shr(i, j + 1) == #shr(i, j) div 2);
const unique $UnknownRef: ref;
diff --git a/Test/test2/strings-where.bpl b/Test/test2/strings-where.bpl
index da529b84..f196899f 100644
--- a/Test/test2/strings-where.bpl
+++ b/Test/test2/strings-where.bpl
@@ -1,4 +1,4 @@
-type real;
+
type elements;
@@ -330,23 +330,23 @@ function #shl(int, int) returns (int);
function #shr(int, int) returns (int);
-axiom (forall x: int, y: int :: { x % y } { x / y } x % y == x - x / y * y);
+axiom (forall x: int, y: int :: { x mod y } { x div y } x mod y == x - x div y * y);
-axiom (forall x: int, y: int :: { x % y } 0 <= x && 0 < y ==> 0 <= x % y && x % y < y);
+axiom (forall x: int, y: int :: { x mod y } 0 <= x && 0 < y ==> 0 <= x mod y && x mod y < y);
-axiom (forall x: int, y: int :: { x % y } 0 <= x && y < 0 ==> 0 <= x % y && x % y < 0 - y);
+axiom (forall x: int, y: int :: { x mod y } 0 <= x && y < 0 ==> 0 <= x mod y && x mod y < 0 - y);
-axiom (forall x: int, y: int :: { x % y } x <= 0 && 0 < y ==> 0 - y < x % y && x % y <= 0);
+axiom (forall x: int, y: int :: { x mod y } x <= 0 && 0 < y ==> 0 - y < x mod y && x mod y <= 0);
-axiom (forall x: int, y: int :: { x % y } x <= 0 && y < 0 ==> y < x % y && x % y <= 0);
+axiom (forall x: int, y: int :: { x mod y } x <= 0 && y < 0 ==> y < x mod y && x mod y <= 0);
-axiom (forall x: int, y: int :: { (x + y) % y } 0 <= x && 0 <= y ==> (x + y) % y == x % y);
+axiom (forall x: int, y: int :: { (x + y) mod y } 0 <= x && 0 <= y ==> (x + y) mod y == x mod y);
-axiom (forall x: int, y: int :: { (y + x) % y } 0 <= x && 0 <= y ==> (y + x) % y == x % y);
+axiom (forall x: int, y: int :: { (y + x) mod y } 0 <= x && 0 <= y ==> (y + x) mod y == x mod y);
-axiom (forall x: int, y: int :: { (x - y) % y } 0 <= x - y && 0 <= y ==> (x - y) % y == x % y);
+axiom (forall x: int, y: int :: { (x - y) mod y } 0 <= x - y && 0 <= y ==> (x - y) mod y == x mod y);
-axiom (forall a: int, b: int, d: int :: { a % d,b % d } 2 <= d && a % d == b % d && a < b ==> a + d <= b);
+axiom (forall a: int, b: int, d: int :: { a mod d,b mod d } 2 <= d && a mod d == b mod d && a < b ==> a + d <= b);
axiom (forall i: int :: { #shl(i, 0) } #shl(i, 0) == i);
@@ -354,7 +354,7 @@ axiom (forall i: int, j: int :: 0 <= j ==> #shl(i, j + 1) == #shl(i, j) * 2);
axiom (forall i: int :: { #shr(i, 0) } #shr(i, 0) == i);
-axiom (forall i: int, j: int :: 0 <= j ==> #shr(i, j + 1) == #shr(i, j) / 2);
+axiom (forall i: int, j: int :: 0 <= j ==> #shr(i, j + 1) == #shr(i, j) div 2);
const unique $UnknownRef: ref;
diff --git a/Test/test20/Answer b/Test/test20/Answer
index efa5bced..fa33507e 100644
--- a/Test/test20/Answer
+++ b/Test/test20/Answer
@@ -118,7 +118,7 @@ axiom (forall x: int :: intSet0[x] == (x == 0 || x == 2 || x == 3));
const intSet1: Set int;
-axiom (forall x: int :: intSet1[x] == (x == 0 - 5 || x == 3));
+axiom (forall x: int :: intSet1[x] == (x == -5 || x == 3));
procedure P();
@@ -126,7 +126,7 @@ procedure P();
implementation P()
{
- assert (forall x: int :: union(intSet0, intSet1)[x] == (x == 0 - 5 || x == 0 || x == 2 || x == 3));
+ assert (forall x: int :: union(intSet0, intSet1)[x] == (x == -5 || x == 0 || x == 2 || x == 3));
}
@@ -143,7 +143,7 @@ axiom (forall x: int :: intSet0[x] <==> x == 0 || x == 2 || x == 3);
const intSet1: Set int;
-axiom (forall x: int :: intSet1[x] <==> x == 0 - 5 || x == 3);
+axiom (forall x: int :: intSet1[x] <==> x == -5 || x == 3);
procedure P();
@@ -151,7 +151,7 @@ procedure P();
implementation P()
{
- assert (forall x: int :: union(intSet0, intSet1)[x] <==> x == 0 - 5 || x == 0 || x == 2 || x == 3);
+ assert (forall x: int :: union(intSet0, intSet1)[x] <==> x == -5 || x == 0 || x == 2 || x == 3);
}
diff --git a/Test/test20/Prog0.bpl b/Test/test20/Prog0.bpl
index ea71b8a8..8fc7b7c7 100644
--- a/Test/test20/Prog0.bpl
+++ b/Test/test20/Prog0.bpl
@@ -1,5 +1,5 @@
// Let's test some Boogie 2 features ...
-type real;
+
type elements;
type Field a;
diff --git a/Test/test20/Prog1.bpl b/Test/test20/Prog1.bpl
index 1d75805c..0e9413c1 100644
--- a/Test/test20/Prog1.bpl
+++ b/Test/test20/Prog1.bpl
@@ -1,5 +1,5 @@
// Let's test some Boogie 2 features ...
-type real;
+
type elements;
type Field a;
diff --git a/Test/test21/Answer b/Test/test21/Answer
index 914e56a1..28aa4e8b 100644
--- a/Test/test21/Answer
+++ b/Test/test21/Answer
@@ -278,6 +278,9 @@ Execution trace:
LargeLiterals0.bpl(7,5): anon0
Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Real.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
--------------------- File NameClash.bpl ----------------------------
Boogie program verifier finished with 1 verified, 0 errors
@@ -549,6 +552,9 @@ Execution trace:
LargeLiterals0.bpl(7,5): anon0
Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Real.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
--------------------- File NameClash.bpl ----------------------------
Boogie program verifier finished with 1 verified, 0 errors
@@ -826,6 +832,9 @@ Execution trace:
LargeLiterals0.bpl(7,5): anon0
Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Real.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
--------------------- File NameClash.bpl ----------------------------
Boogie program verifier finished with 1 verified, 0 errors
diff --git a/Test/test21/Real.bpl b/Test/test21/Real.bpl
new file mode 100644
index 00000000..3dcf3ea3
--- /dev/null
+++ b/Test/test21/Real.bpl
@@ -0,0 +1,17 @@
+axiom (forall r: real :: r == 0.0 || r / r == 1.0);
+
+procedure P(a: real, b: real) returns () {
+ assume a >= b && a != 0.0 && a >= 1.3579;
+
+ assert 2e0 * (a + 3.0) - 0.5 >= b;
+ assert 2e0 * (a + 3.0) - 0.5 > b;
+ assert b <= 2e0 * (a + 3.0) - 0.5;
+ assert b < 2e0 * (a + 3.0) - 0.5;
+
+ assert 1/2 <= 0.65;
+ assert a > 100e-2 ==> 1 / a <= a;
+ assert a / 2 != a || a == 0.00;
+ assert a != 0.0 ==> a / a == 1.0;
+
+ assert int(a) >= 0 ==> real(3) * a > a;
+} \ No newline at end of file
diff --git a/Test/test21/runtest.bat b/Test/test21/runtest.bat
index d994a4da..bfdcc570 100644
--- a/Test/test21/runtest.bat
+++ b/Test/test21/runtest.bat
@@ -4,6 +4,7 @@ setlocal
set BGEXE=..\..\Binaries\Boogie.exe
rem set BGEXE=mono ..\..\Binaries\Boogie.exe
+
for %%m in (
n p a
) do (
@@ -16,7 +17,8 @@ for %%f in (DisjointDomains.bpl DisjointDomains2.bpl FunAxioms.bpl
Keywords.bpl Casts.bpl BooleanQuantification.bpl EmptyList.bpl Boxing.bpl
MapOutputTypeParams.bpl ParallelAssignment.bpl BooleanQuantification2.bpl
Flattening.bpl Orderings.bpl Orderings2.bpl Orderings3.bpl Orderings4.bpl
- EmptySetBug.bpl Coercions2.bpl MapAxiomsConsistency.bpl LargeLiterals0.bpl) do (
+ EmptySetBug.bpl Coercions2.bpl MapAxiomsConsistency.bpl LargeLiterals0.bpl
+ Real.bpl) do (
echo --------------------- File %%f ----------------------------
%BGEXE% %* /typeEncoding:%%m /logPrefix:0%%m %%f
)
diff --git a/Util/Emacs/boogie-mode.el b/Util/Emacs/boogie-mode.el
index 5b60dcab..5763d695 100644
--- a/Util/Emacs/boogie-mode.el
+++ b/Util/Emacs/boogie-mode.el
@@ -36,9 +36,9 @@
)) . font-lock-builtin-face)
`(,(boogie-regexp-opt '(
"assert" "assume" "break" "call" "then" "else" "havoc" "if" "goto" "return" "while"
- "old" "forall" "exists" "lambda" "cast"
+ "old" "forall" "exists" "lambda" "cast" "div" "mod"
"false" "true")) . font-lock-keyword-face)
- `(,(boogie-regexp-opt '("bool" "int"
+ `(,(boogie-regexp-opt '("bool" "int" "real"
"bv0" "bv1" "bv2" "bv3" "bv4" "bv5" "bv6" "bv7" "bv8" "bv9"
"bv10" "bv11" "bv12" "bv13" "bv14" "bv15" "bv16" "bv17" "bv18" "bv19"
"bv20" "bv21" "bv22" "bv23" "bv24" "bv25" "bv26" "bv27" "bv28" "bv29"
diff --git a/Util/Emacs/dafny-mode.el b/Util/Emacs/dafny-mode.el
index 4f437d23..1ba6186b 100644
--- a/Util/Emacs/dafny-mode.el
+++ b/Util/Emacs/dafny-mode.el
@@ -40,7 +40,7 @@
`(,(dafny-regexp-opt '(
"assert" "assume" "break" "choose" "then" "else" "if" "label" "return" "yield"
"while" "print" "where"
- "old" "forall" "exists" "new" "parallel" "in" "this" "fresh"
+ "old" "forall" "exists" "new" "parallel" "calc" "in" "this" "fresh"
"match" "case" "false" "true" "null")) . font-lock-keyword-face)
`(,(dafny-regexp-opt '("array" "array2" "array3" "bool" "multiset" "map" "nat" "int" "object" "set" "seq")) . font-lock-type-face)
)
diff --git a/Util/VS2010/Boogie/BoogieLanguageService/Grammar.cs b/Util/VS2010/Boogie/BoogieLanguageService/Grammar.cs
index 02d14b93..fd7c561d 100644
--- a/Util/VS2010/Boogie/BoogieLanguageService/Grammar.cs
+++ b/Util/VS2010/Boogie/BoogieLanguageService/Grammar.cs
@@ -23,17 +23,17 @@ namespace Demo
"bv30", "bv31", "bv32",
"bv64",
"call", "complete", "const",
+ "div",
"else", "ensures", "exists", "extends",
"false", "forall", "free", "function",
"goto",
"havoc",
"if", "implementation", "int", "invariant",
"lambda",
- "modifies",
+ "mod", "modifies",
"old",
"procedure",
- "requires",
- "return", "returns",
+ "real", "requires", "return", "returns",
"then", "true", "type",
"unique",
"var",
@@ -181,7 +181,7 @@ namespace Demo
identList.Rule = MakePlusRule(identList, comma, ident);
NewStmt.Rule = "new" + QualifiedName + GenericsPostfix.Q() + LParen + expressionList.Q() + RParen;
NewArrStmt.Rule = "new" + QualifiedName + GenericsPostfix.Q() + LBracket + expressionList.Q() + RBracket;
- BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "%" | "^" | "&" | "|"
+ BinOp.Rule = ToTerm("+") | "-" | "*" | "div" | "mod" | "^" | "&" | "|"
| "&&" | "||" | "==" | "!=" | greater | less
| ">=" | "<=" | "is"
| "=" | "+=" | "-="
@@ -270,8 +270,7 @@ namespace Demo
"modifies" |
"old" |
"procedure" |
- "requires" |
- "return" | "returns" |
+ "real" | "requires" | "return" | "returns" |
"then" | "true" | "type" |
"unique" |
"var" |
@@ -322,7 +321,7 @@ namespace Demo
;
typeDecl.Rule
- = (ToTerm("int") | "bool" | ident)
+ = (ToTerm("int") | "bool" | "real" | ident)
;
fieldDecl.Rule
@@ -376,7 +375,7 @@ namespace Demo
#region 5. Operators precedence
RegisterOperators(1, "<==>");
RegisterOperators(2, "+", "-");
- RegisterOperators(3, "*", "/", "%", "!!");
+ RegisterOperators(3, "*", "div", "mod", "!!");
RegisterOperators(4, Associativity.Right, "^");
RegisterOperators(5, "||");
RegisterOperators(6, "&&");
diff --git a/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs b/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs
index 9d6f0882..ac1b755c 100644
--- a/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs
+++ b/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs
@@ -29,7 +29,7 @@ namespace Demo
"in", "forall", "exists",
"seq", "set", "map", "multiset", "array", "array2", "array3",
"match", "case",
- "fresh", "old", "choose", "where"
+ "fresh", "old", "choose", "where", "calc"
);
StringLiteral s = new StringLiteral("String", "'", StringFlags.AllowsDoubledQuote);
@@ -292,6 +292,7 @@ namespace Demo
| "return"
| "yield"
| "parallel"
+ | "calc"
| "print"
| "returns"
| "yields"
diff --git a/Util/VS2010/DafnyExtension/DafnyExtension.sln b/Util/VS2010/DafnyExtension/DafnyExtension.sln
index e7391254..fd450cc8 100644
--- a/Util/VS2010/DafnyExtension/DafnyExtension.sln
+++ b/Util/VS2010/DafnyExtension/DafnyExtension.sln
@@ -1,6 +1,6 @@

-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DafnyExtension", "DafnyExtension\DafnyExtension.csproj", "{6E9A5E14-0763-471C-A129-80A879D9E7BA}"
EndProject
Global
diff --git a/Util/VS2010/DafnyExtension/DafnyExtension/DafnyDriver.cs b/Util/VS2010/DafnyExtension/DafnyExtension/DafnyDriver.cs
index 9f22b887..39829bb0 100644
--- a/Util/VS2010/DafnyExtension/DafnyExtension/DafnyDriver.cs
+++ b/Util/VS2010/DafnyExtension/DafnyExtension/DafnyDriver.cs
@@ -231,9 +231,6 @@ namespace DafnyLanguage
if (Bpl.CommandLineOptions.Clo.UseAbstractInterpretation) {
if (Bpl.CommandLineOptions.Clo.Ai.J_Intervals || Bpl.CommandLineOptions.Clo.Ai.J_Trivial) {
Microsoft.Boogie.AbstractInterpretation.NativeAbstractInterpretation.RunAbstractInterpretation(program);
- } else if (Bpl.CommandLineOptions.Clo.Ai.AnySet) {
- // run one of the old domains
- Microsoft.Boogie.AbstractInterpretation.AbstractInterpretation.RunAbstractInterpretation(program);
} else {
// use /infer:j as the default
Bpl.CommandLineOptions.Clo.Ai.J_Intervals = true;
@@ -258,11 +255,7 @@ namespace DafnyLanguage
ConditionGeneration vcgen = null;
try {
- if (Bpl.CommandLineOptions.Clo.vcVariety == Bpl.CommandLineOptions.VCVariety.Doomed) {
- vcgen = new DCGen(program, Bpl.CommandLineOptions.Clo.SimplifyLogFilePath, Bpl.CommandLineOptions.Clo.SimplifyLogFileAppend);
- } else {
- vcgen = new VCGen(program, Bpl.CommandLineOptions.Clo.SimplifyLogFilePath, Bpl.CommandLineOptions.Clo.SimplifyLogFileAppend);
- }
+ vcgen = new VCGen(program, Bpl.CommandLineOptions.Clo.SimplifyLogFilePath, Bpl.CommandLineOptions.Clo.SimplifyLogFileAppend);
} catch (Bpl.ProverException) {
return PipelineOutcome.FatalError;
}
diff --git a/Util/VS2010/DafnyExtension/DafnyExtension/DafnyExtension.csproj b/Util/VS2010/DafnyExtension/DafnyExtension/DafnyExtension.csproj
index 66370dec..2580c396 100644
--- a/Util/VS2010/DafnyExtension/DafnyExtension/DafnyExtension.csproj
+++ b/Util/VS2010/DafnyExtension/DafnyExtension/DafnyExtension.csproj
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -14,6 +15,12 @@
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<GeneratePkgDefFile>false</GeneratePkgDefFile>
+ <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ <OldToolsVersion>4.0</OldToolsVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -158,8 +165,13 @@
<ItemGroup>
<WCFMetadata Include="Service References\" />
</ItemGroup>
+ <PropertyGroup>
+ <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
+ <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+ </PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\VSSDK\Microsoft.VsSDK.targets" />
+ <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\VSSDK\Microsoft.VsSDK.targets" Condition="false" />
<PropertyGroup>
<PostBuildEvent>cd</PostBuildEvent>
<PostBuildEvent>
diff --git a/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs b/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs
index 22388704..2f295429 100644
--- a/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs
+++ b/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs
@@ -227,10 +227,12 @@ namespace DafnyLanguage
#region keywords
case "allocated":
case "array":
+ case "as":
case "assert":
case "assume":
case "bool":
case "break":
+ case "calc":
case "case":
case "choose":
case "class":
@@ -249,7 +251,7 @@ namespace DafnyLanguage
case "function":
case "ghost":
case "if":
- case "imports":
+ case "import":
case "in":
case "int":
case "invariant":
@@ -265,6 +267,7 @@ namespace DafnyLanguage
case "null":
case "object":
case "old":
+ case "opened":
case "parallel":
case "predicate":
case "print":
diff --git a/Util/VS2010/DafnyExtension/DafnyExtension/source.extension.vsixmanifest b/Util/VS2010/DafnyExtension/DafnyExtension/source.extension.vsixmanifest
index d822fbfc..ef5c1cf5 100644
--- a/Util/VS2010/DafnyExtension/DafnyExtension/source.extension.vsixmanifest
+++ b/Util/VS2010/DafnyExtension/DafnyExtension/source.extension.vsixmanifest
@@ -10,6 +10,9 @@
<VisualStudio Version="10.0">
<Edition>Pro</Edition>
</VisualStudio>
+ <VisualStudio Version="11.0">
+ <Edition>Pro</Edition>
+ </VisualStudio>
</SupportedProducts>
<SupportedFrameworkRuntimeEdition MinVersion="4.0" MaxVersion="4.0" />
</Identifier>
diff --git a/Util/latex/boogie.sty b/Util/latex/boogie.sty
index 45eb050d..e67c61f4 100644
--- a/Util/latex/boogie.sty
+++ b/Util/latex/boogie.sty
@@ -19,7 +19,7 @@
\usepackage{listings}
\lstdefinelanguage{boogie}{
- morekeywords={type,finite,bool,int,ref,%
+ morekeywords={type,bool,int,real,%
bv0,bv1,bv2,bv3,bv4,bv5,bv6,bv7,bv8,bv9,%
bv10,bv11,bv12,bv13,bv14,bv15,bv16,bv17,bv18,bv19,%
bv20,bv21,bv22,bv23,bv24,bv25,bv26,bv27,bv28,bv29,%
@@ -34,7 +34,7 @@
procedure,implementation,
requires,modifies,ensures,free,
% expressions
- false,true,null,old,then,
+ false,true,null,old,then,div,mod,
% statements
assert,assume,havoc,call,if,else,while,invariant,break,return,goto,
},
diff --git a/Util/latex/dafny.sty b/Util/latex/dafny.sty
index 88f9c2a2..879b90cb 100644
--- a/Util/latex/dafny.sty
+++ b/Util/latex/dafny.sty
@@ -15,7 +15,7 @@
match,case,false,true,null,old,fresh,choose,this,
% statements
assert,assume,print,new,if,then,else,while,invariant,break,label,return,yield,
- parallel,where
+ parallel,where,calc
},
literate=%
{:}{$\colon$}1
diff --git a/Util/vim/syntax/boogie.vim b/Util/vim/syntax/boogie.vim
index 667a2b8c..6af66279 100644
--- a/Util/vim/syntax/boogie.vim
+++ b/Util/vim/syntax/boogie.vim
@@ -13,9 +13,9 @@ set cpo&vim
" type
-syn keyword bplType bool int
+syn keyword bplType bool int real
" repeat / condition / label
-syn keyword bplExpr forall exists cast returns lambda
+syn keyword bplExpr forall exists cast returns lambda div mod
syn keyword bplStmt goto return while call else if assert assume havoc then
syn keyword bplDecl axiom function procedure type requires ensures modifies unique const var free implementation invariant
" user labels
diff --git a/Util/vim/syntax/dafny.vim b/Util/vim/syntax/dafny.vim
index d67d275a..45afbcf0 100644
--- a/Util/vim/syntax/dafny.vim
+++ b/Util/vim/syntax/dafny.vim
@@ -10,7 +10,7 @@ syntax keyword dafnyTypeDef class datatype codatatype type iterator
syntax keyword module import opened as default
syntax keyword dafnyConditional if then else match case
syntax keyword dafnyRepeat while parallel
-syntax keyword dafnyStatement assume assert return yield new print break label where
+syntax keyword dafnyStatement assume assert return yield new print break label where calc
syntax keyword dafnyKeyword var ghost returns yields null static this refines
syntax keyword dafnyType bool nat int seq set multiset object array array2 array3 map
syntax keyword dafnyLogic requires ensures modifies reads decreases invariant
diff --git a/_admin/Boogie/aste/summary.log b/_admin/Boogie/aste/summary.log
index 65d20cc8..a74bf079 100644
--- a/_admin/Boogie/aste/summary.log
+++ b/_admin/Boogie/aste/summary.log
@@ -1,45 +1,349 @@
-# Aste started: 2012-08-22 07:00:02
+# Aste started: 2012-10-04 07:00:01
# Host id: Boogiebox
# Configuration: boogie.cfg
# Task: aste.tasks.boogie.FullBuild
-# [2012-08-22 07:01:12] SpecSharp revision: 5f64084327c6
-# [2012-08-22 07:01:12] SscBoogie revision: 5f64084327c6
-# [2012-08-22 07:02:05] Boogie revision: 693e9d4632c3
-[2012-08-22 07:03:35] C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com SpecSharp.sln /Project "Checkin Tests" /Build
+# [2012-10-04 07:01:18] SpecSharp revision: 394202217a94
+# [2012-10-04 07:01:18] SscBoogie revision: 394202217a94
+# [2012-10-04 07:02:23] Boogie revision: aa44b4ba2f56
+[2012-10-04 07:03:47] C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com SpecSharp.sln /Project "Checkin Tests" /Build
1>corflags : warning CF011: The specified file is strong name signed. Using /Force will invalidate the signature of this image and will require the assembly to be resigned.
warning CF011: The specified file is strong name signed. Using /Force will invalidate the signature of this image and will require the assembly to be resigned.
-[2012-08-22 07:05:01] C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com Boogie.sln /Rebuild Checked
+[2012-10-04 07:04:11] [Error] C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com Dafny.sln /Rebuild Checked
- D:\Temp\aste\Boogie\Source\Core\AbsyType.cs(823,16): warning CS0659: 'Microsoft.Boogie.BasicType' overrides Object.Equals(object o) but does not override Object.GetHashCode()
- D:\Temp\aste\Boogie\Source\Core\AbsyType.cs(2802,16): warning CS0659: 'Microsoft.Boogie.CtorType' overrides Object.Equals(object o) but does not override Object.GetHashCode()
- D:\Temp\aste\Boogie\Source\Core\OOLongUtil.cs(109,7): warning CS0162: Unreachable code detected
- D:\Temp\aste\Boogie\Source\Core\Absy.cs(770,7): warning CC1036: Detected call to method 'Graphing.Graph`1<Microsoft.Boogie.Block>.TopologicalSort' without [Pure] in contracts of method 'Microsoft.Boogie.Program.GraphFromImpl(Microsoft.Boogie.Implementation)'.
- EXEC : warning CC1079: Type Microsoft.Boogie.Variable implements Microsoft.AbstractInterpretationFramework.IVariable.get_Name by inheriting Microsoft.Boogie.NamedDeclaration.get_Name causing the interface contract to not be checked at runtime. Consider adding a wrapper method.
- D:\Temp\aste\Boogie\Source\Core\Parser.cs(128,3): warning CC1032: Method 'Microsoft.Boogie.Parser+BvBounds.Resolve(Microsoft.Boogie.ResolutionContext)' overrides 'Microsoft.Boogie.Absy.Resolve(Microsoft.Boogie.ResolutionContext)', thus cannot add Requires.
- D:\Temp\aste\Boogie\Source\Core\Parser.cs(133,5): warning CC1032: Method 'Microsoft.Boogie.Parser+BvBounds.Emit(Microsoft.Boogie.TokenTextWriter,System.Int32,System.Boolean)' overrides 'Microsoft.Boogie.Expr.Emit(Microsoft.Boogie.TokenTextWriter,System.Int32,System.Boolean)', thus cannot add Requires.
- D:\Temp\aste\Boogie\Source\Core\Parser.cs(136,74): warning CC1032: Method 'Microsoft.Boogie.Parser+BvBounds.ComputeFreeVariables(Microsoft.Boogie.GSet`1<System.Object>)' overrides 'Microsoft.Boogie.Expr.ComputeFreeVariables(Microsoft.Boogie.GSet`1<System.Object>)', thus cannot add Requires.
- D:\Temp\aste\Boogie\Source\AbsInt\ExprFactories.cs(247,7): warning CS0162: Unreachable code detected
- D:\Temp\aste\Boogie\Source\AbsInt\ExprFactories.cs(266,7): warning CS0162: Unreachable code detected
- D:\Temp\aste\Boogie\Source\AbsInt\IntervalDomain.cs(49,9): warning CC1036: Detected call to method 'Microsoft.Boogie.AbstractInterpretation.NativeIntervallDomain+Node.StrictlyBefore(Microsoft.Boogie.Variable,Microsoft.Boogie.Variable)' without [Pure] in contracts of method 'Microsoft.Boogie.AbstractInterpretation.NativeIntervallDomain+Node.#ctor(Microsoft.Boogie.Variable,System.Nullable`1<System.Numerics.BigInteger>,System.Nullable`1<System.Numerics.BigInteger>,Microsoft.Boogie.AbstractInterpretation.NativeIntervallDomain+Node)'.
- D:\Temp\aste\Boogie\Source\VCGeneration\VC.cs(1400,11): warning CS0162: Unreachable code detected
- D:\Temp\aste\Boogie\Source\VCGeneration\VC.cs(1558,11): warning CS0162: Unreachable code detected
- EXEC : warning CC1032: Method 'Microsoft.Boogie.Houdini.InlineRequiresVisitor.VisitCmdSeq(Microsoft.Boogie.CmdSeq)' overrides 'Microsoft.Boogie.StandardVisitor.VisitCmdSeq(Microsoft.Boogie.CmdSeq)', thus cannot add Requires.
- EXEC : warning CC1032: Method 'Microsoft.Boogie.Houdini.FreeRequiresVisitor.VisitAssertRequiresCmd(Microsoft.Boogie.AssertRequiresCmd)' overrides 'Microsoft.Boogie.StandardVisitor.VisitAssertRequiresCmd(Microsoft.Boogie.AssertRequiresCmd)', thus cannot add Requires.
- warning CS0659: 'Microsoft.Boogie.BasicType' overrides Object.Equals(object o) but does not override Object.GetHashCode()
- warning CS0659: 'Microsoft.Boogie.CtorType' overrides Object.Equals(object o) but does not override Object.GetHashCode()
- warning CS0162: Unreachable code detected
- warning CC1036: Detected call to method 'Graphing.Graph`1<Microsoft.Boogie.Block>.TopologicalSort' without [Pure] in contracts of method 'Microsoft.Boogie.Program.GraphFromImpl(Microsoft.Boogie.Implementation)'.
- warning CC1079: Type Microsoft.Boogie.Variable implements Microsoft.AbstractInterpretationFramework.IVariable.get_Name by inheriting Microsoft.Boogie.NamedDeclaration.get_Name causing the interface contract to not be checked at runtime. Consider adding a wrapper method.
- warning CC1032: Method 'Microsoft.Boogie.Parser+BvBounds.Resolve(Microsoft.Boogie.ResolutionContext)' overrides 'Microsoft.Boogie.Absy.Resolve(Microsoft.Boogie.ResolutionContext)', thus cannot add Requires.
- warning CC1032: Method 'Microsoft.Boogie.Parser+BvBounds.Emit(Microsoft.Boogie.TokenTextWriter,System.Int32,System.Boolean)' overrides 'Microsoft.Boogie.Expr.Emit(Microsoft.Boogie.TokenTextWriter,System.Int32,System.Boolean)', thus cannot add Requires.
- warning CC1032: Method 'Microsoft.Boogie.Parser+BvBounds.ComputeFreeVariables(Microsoft.Boogie.GSet`1<System.Object>)' overrides 'Microsoft.Boogie.Expr.ComputeFreeVariables(Microsoft.Boogie.GSet`1<System.Object>)', thus cannot add Requires.
- warning CS0162: Unreachable code detected
- warning CS0162: Unreachable code detected
- warning CC1036: Detected call to method 'Microsoft.Boogie.AbstractInterpretation.NativeIntervallDomain+Node.StrictlyBefore(Microsoft.Boogie.Variable,Microsoft.Boogie.Variable)' without [Pure] in contracts of method 'Microsoft.Boogie.AbstractInterpretation.NativeIntervallDomain+Node.#ctor(Microsoft.Boogie.Variable,System.Nullable`1<System.Numerics.BigInteger>,System.Nullable`1<System.Numerics.BigInteger>,Microsoft.Boogie.AbstractInterpretation.NativeIntervallDomain+Node)'.
- warning CS0162: Unreachable code detected
- warning CS0162: Unreachable code detected
- warning CC1032: Method 'Microsoft.Boogie.Houdini.InlineRequiresVisitor.VisitCmdSeq(Microsoft.Boogie.CmdSeq)' overrides 'Microsoft.Boogie.StandardVisitor.VisitCmdSeq(Microsoft.Boogie.CmdSeq)', thus cannot add Requires.
- warning CC1032: Method 'Microsoft.Boogie.Houdini.FreeRequiresVisitor.VisitAssertRequiresCmd(Microsoft.Boogie.AssertRequiresCmd)' overrides 'Microsoft.Boogie.StandardVisitor.VisitAssertRequiresCmd(Microsoft.Boogie.AssertRequiresCmd)', thus cannot add Requires.
-[2012-08-22 07:59:27] 0 out of 33 test(s) in D:\Temp\aste\Boogie\Test\alltests.txt failed
-# [2012-08-22 08:00:38] Released nightly of Boogie
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(12,17): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(11,17): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2891,40): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\cce.cs(5,17): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyOptions.cs(6,23): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Scanner.cs(8,17): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(3,17): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(11,17): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(10,23): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(85,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(93,36): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(100,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(108,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(115,33): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(123,39): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3421,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3428,32): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3594,30): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3598,35): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3598,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5945,82): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6020,42): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6649,14): error CS0246: The type or namespace name 'ExprSeq' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6666,46): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6681,36): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6691,36): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6703,36): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6716,38): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6725,38): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6755,39): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6763,43): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6763,55): error CS0246: The type or namespace name 'Expr' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6763,66): error CS0246: The type or namespace name 'Expr' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6763,74): error CS0246: The type or namespace name 'Expr' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6780,45): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6780,57): error CS0246: The type or namespace name 'Expr' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6780,68): error CS0246: The type or namespace name 'Expr' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6780,76): error CS0246: The type or namespace name 'Expr' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6780,84): error CS0246: The type or namespace name 'Expr' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6802,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6846,36): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6903,33): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6911,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6926,37): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6936,35): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(6967,37): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(1041,25): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(1068,41): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(1089,46): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(1097,41): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(1343,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(1350,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(1356,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(1383,27): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(1514,30): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(1703,95): error CS0246: The type or namespace name 'StmtListBuilder' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(1727,29): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(1727,112): error CS0246: The type or namespace name 'StmtListBuilder' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(2187,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(2714,47): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(2835,34): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(2879,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3277,52): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3277,20): error CS0246: The type or namespace name 'QKeyValue' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3282,52): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3282,76): error CS0246: The type or namespace name 'QKeyValue' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3282,20): error CS0246: The type or namespace name 'QKeyValue' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3448,62): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3475,34): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3505,51): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3665,25): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(3678,27): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(4366,25): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(4760,54): error CS0246: The type or namespace name 'VariableSeq' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(4855,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(4970,40): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(4984,36): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(4997,36): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5030,88): error CS0246: The type or namespace name 'StmtListBuilder' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5083,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5140,34): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5224,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5283,29): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5421,34): error CS0246: The type or namespace name 'Expr' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5436,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5535,93): error CS0246: The type or namespace name 'StmtListBuilder' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5751,40): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5850,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5850,36): error CS0246: The type or namespace name 'Expr' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5850,56): error CS0246: The type or namespace name 'StmtListBuilder' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5862,33): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5862,45): error CS0246: The type or namespace name 'Expr' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(5873,34): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(7064,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(7324,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(7334,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(7349,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Translator.cs(8160,19): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Rewriter.cs(26,31): error CS0246: The type or namespace name 'Boogie' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Rewriter.cs(270,28): error CS0246: The type or namespace name 'Boogie' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Rewriter.cs(335,42): error CS0246: The type or namespace name 'Boogie' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Printer.cs(12,23): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\cce.cs(26,38): error CS0246: The type or namespace name 'VariableSeq' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\RefinementTransformer.cs(19,26): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Cloner.cs(6,26): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Scanner.cs(232,2): error CS0246: The type or namespace name 'Token' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Scanner.cs(241,2): error CS0246: The type or namespace name 'Token' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Scanner.cs(242,2): error CS0246: The type or namespace name 'Token' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Scanner.cs(555,2): error CS0246: The type or namespace name 'Token' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Scanner.cs(789,9): error CS0246: The type or namespace name 'Token' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Scanner.cs(800,9): error CS0246: The type or namespace name 'Token' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Compiler.cs(11,23): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(33,9): error CS0246: The type or namespace name 'Token' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(34,9): error CS0246: The type or namespace name 'Token' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(143,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(449,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(459,30): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(470,17): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(757,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(764,46): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(775,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(818,29): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(847,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(919,90): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(989,47): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(989,69): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(1065,25): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(1147,47): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(1147,69): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(1988,18): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(2258,17): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(2351,17): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(2430,17): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(2666,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(2679,28): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Parser.cs(3237,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(22,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(53,25): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(306,29): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(314,35): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(411,59): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(695,28): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(904,52): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(1586,34): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(2350,29): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(3790,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(3848,30): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(3966,47): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(3981,51): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(5232,45): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\Resolver.cs(5266,70): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyMain.cs(10,23): error CS0234: The type or namespace name 'Boogie' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(62,38): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(151,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(160,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(166,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(433,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(434,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(471,28): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(471,110): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(486,28): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(501,28): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(742,12): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(743,12): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(744,12): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(757,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(809,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(823,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(844,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(846,33): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(846,47): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(857,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(859,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(862,36): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(862,50): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(862,93): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(896,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(912,29): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(912,90): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(974,25): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1010,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1062,25): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1088,28): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1102,27): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1131,25): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1154,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1196,18): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1203,18): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1218,25): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1238,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1268,30): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1346,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1433,30): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1454,19): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1483,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1497,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1508,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1531,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1532,51): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1568,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1569,52): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1582,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1583,52): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1616,19): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1650,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1673,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1697,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1703,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1752,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1757,18): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1773,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1780,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1794,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1802,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1816,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1843,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1849,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1860,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1880,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1900,28): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1954,20): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1960,20): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(1967,20): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2020,20): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2054,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2064,36): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2082,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2098,36): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2109,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2114,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2114,83): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2144,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2154,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2175,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2229,20): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2318,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2347,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2368,19): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2396,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2405,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2423,28): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2458,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2498,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2531,29): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2547,32): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2615,25): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2688,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2785,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2819,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2851,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2853,30): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2867,30): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2867,47): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2893,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2894,28): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2930,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2930,38): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2937,12): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2938,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2945,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(2988,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3009,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3036,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3042,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3050,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3057,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3080,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3097,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3113,29): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3129,27): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3145,36): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3156,30): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3168,27): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3176,32): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3184,27): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3192,27): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3210,28): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3235,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3266,28): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3291,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3314,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3330,29): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3330,73): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3368,20): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3391,32): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3410,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3436,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3680,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3703,20): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3725,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3727,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3732,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3732,82): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3812,30): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3833,27): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3843,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3861,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3882,29): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3894,29): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3906,25): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3916,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3936,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3947,23): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(3968,20): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4000,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4021,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4032,22): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4050,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4161,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4176,28): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4193,37): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4208,29): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4219,31): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4247,24): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4259,26): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4260,21): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4262,36): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ D:\Temp\aste\Boogie\Source\Dafny\DafnyAst.cs(4262,52): error CS0246: The type or namespace name 'IToken' could not be found (are you missing a using directive or an assembly reference?)
+ C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1360,9): warning MSB3245: Could not resolve this reference. Could not locate the assembly "Basetypes". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1360,9): warning MSB3245: Could not resolve this reference. Could not locate the assembly "Core". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1360,9): warning MSB3245: Could not resolve this reference. Could not locate the assembly "ParserHelper". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ error CS0006: Metadata file 'D:\Temp\aste\Boogie\Source\Dafny\bin\Checked\DafnyPipeline.dll' could not be found
+ C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1360,9): warning MSB3245: Could not resolve this reference. Could not locate the assembly "AbsInt". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1360,9): warning MSB3245: Could not resolve this reference. Could not locate the assembly "Core". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1360,9): warning MSB3245: Could not resolve this reference. Could not locate the assembly "ParserHelper". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1360,9): warning MSB3245: Could not resolve this reference. Could not locate the assembly "VCGeneration". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ warning MSB3245: Could not resolve this reference. Could not locate the assembly "Basetypes". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ warning MSB3245: Could not resolve this reference. Could not locate the assembly "Core". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ warning MSB3245: Could not resolve this reference. Could not locate the assembly "ParserHelper". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ warning MSB3245: Could not resolve this reference. Could not locate the assembly "AbsInt". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ warning MSB3245: Could not resolve this reference. Could not locate the assembly "Core". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ warning MSB3245: Could not resolve this reference. Could not locate the assembly "ParserHelper". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ warning MSB3245: Could not resolve this reference. Could not locate the assembly "VCGeneration". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
+ 318 error
+ 1 error
+ 2 failed